demi` patch: Added a new "Video Details" dialog, that lists some information regarding the currently open video.

Originally committed to SVN as r1520.
This commit is contained in:
Rodrigo Braz Monteiro 2007-08-19 22:21:41 +00:00
parent f401f216dc
commit d6b5c8fbb9
12 changed files with 229 additions and 1 deletions

View file

@ -156,6 +156,7 @@ aegisub_SOURCES = \
dialog_tip.cpp \ dialog_tip.cpp \
dialog_translation.cpp \ dialog_translation.cpp \
dialog_version_check.cpp \ dialog_version_check.cpp \
dialog_video_details.cpp \
drop.cpp \ drop.cpp \
export_clean_info.cpp \ export_clean_info.cpp \
export_fixstyle.cpp \ export_fixstyle.cpp \

View file

@ -159,6 +159,7 @@ Please visit http://aegisub.net to download latest version
- Joining of two lines will no longer take the timings of any line that starts and ends at 0 into consideration. (AMZ) - Joining of two lines will no longer take the timings of any line that starts and ends at 0 into consideration. (AMZ)
- Added a "new window" command to the file menu, to launch a new instance of Aegisub. (AMZ) - Added a "new window" command to the file menu, to launch a new instance of Aegisub. (AMZ)
- Added "Effect" field to the Select Lines dialog. (demi`) - Added "Effect" field to the Select Lines dialog. (demi`)
- Added a new "Video Details" dialog, that lists some information regarding the currently open video. (demi`)
= 1.10 beta - 2006.08.07 =========================== = 1.10 beta - 2006.08.07 ===========================

View file

@ -0,0 +1,130 @@
// Copyright (c) 2007, Alysson Souza e Silva (demi_alucard)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
///////////
// Headers
#include "dialog_video_details.h"
#include "video_context.h"
#include "video_provider.h"
#include "audio_provider.h"
#include "audio_box.h"
#include "utils.h"
///////////////
// Constructor
DialogVideoDetails::DialogVideoDetails(wxWindow *parent)
: wxDialog(parent , -1, _("Video Details"),wxDefaultPosition,wxDefaultSize)
{
// Main controls
wxFlexGridSizer *fg = new wxFlexGridSizer(2, 5, 10);
wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
wxStaticBoxSizer *video_sizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Video"));
VideoProvider *vprovider = VideoContext::Get()->GetProvider();
int width = vprovider->GetWidth();
int height = vprovider->GetHeight();
int framecount = vprovider->GetFrameCount();
double fps = vprovider->GetFPS();
wxTextCtrl *fname_text = new wxTextCtrl(this, -1, VideoContext::Get()->videoName, wxDefaultPosition, wxSize(300,-1), wxTE_READONLY);
wxTextCtrl *fps_text = new wxTextCtrl(this, -1, wxString::Format(_T("%.3f"), fps), wxDefaultPosition, wxDefaultSize, wxTE_READONLY);
wxTextCtrl *resolution_text = new wxTextCtrl(this, -1, wxString::Format(_T("%dx%d (%s)"), width, height, PrettyAR(width, height)), wxDefaultPosition, wxDefaultSize, wxTE_READONLY);
wxTextCtrl *length_text = new wxTextCtrl(this, -1, wxString::Format(_T("%d frames (%s)"), framecount, PrettyTimeStamp(framecount, fps)), wxDefaultPosition, wxDefaultSize, wxTE_READONLY);
wxTextCtrl *decoder_text = new wxTextCtrl(this, -1, vprovider->GetDecoderName(), wxDefaultPosition, wxDefaultSize, wxTE_READONLY);
fg->Add(new wxStaticText(this, -1, _("File name:")), 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
fg->Add(fname_text, 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
fg->Add(new wxStaticText(this, -1, _("FPS:")), 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
fg->Add(fps_text, 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
fg->Add(new wxStaticText(this, -1, _("Resolution:")), 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
fg->Add(resolution_text, 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
fg->Add(new wxStaticText(this, -1, _("Length:")), 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
fg->Add(length_text, 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
fg->Add(new wxStaticText(this, -1, _("Decoder:")), 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
fg->Add(decoder_text, 0, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
video_sizer->Add(fg);
main_sizer->Add(video_sizer, 1, wxALL|wxEXPAND, 5);
main_sizer->Add(CreateSeparatedButtonSizer(wxOK), 0, wxALL|wxEXPAND, 5);
main_sizer->SetSizeHints(this);
SetSizer(main_sizer);
CenterOnParent();
}
////////////
// PrettyAR
wxString DialogVideoDetails::PrettyAR(int width, int height)
{
int limit = (int)ceil(sqrt(double(MIN(width, height))));
for (int i=2;i<=limit;i++) {
while (width % i == 0 && height % i == 0) {
width /= i;
height /= i;
}
}
return wxString::Format(_T("%d:%d"), width, height);
}
///////////////////
// PrettyTimeStamp
wxString DialogVideoDetails::PrettyTimeStamp(int frames, double fps)
{
int tt = int(frames / fps * 1000);
int cs = tt % 1000; tt /= 1000;
int s = tt % 60; tt /= 60;
int m = tt % 60; tt /= 60;
int h = tt;
return wxString::Format(_T("%d:%02d:%02d.%03d"), h, m, s, cs);
}
//////////////
// Destructor
DialogVideoDetails::~DialogVideoDetails()
{
}
///////////////
// Event table
BEGIN_EVENT_TABLE(DialogVideoDetails,wxDialog)
END_EVENT_TABLE()

View file

@ -0,0 +1,58 @@
// Copyright (c) 2007, Alysson Souza e Silva (demi_alucard)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
#ifndef _DIALOG_VIDEO_DETAILS_H
#define _DIALOG_VIDEO_DETAILS_H
///////////
// Headers
#include <wx/dialog.h>
class DialogVideoDetails : public wxDialog {
private:
wxString PrettyTimeStamp(int frames, double fps);
wxString PrettyAR(int width, int height);
int width, height;
int framecount, fps;
public:
DialogVideoDetails(wxWindow *parent);
virtual ~DialogVideoDetails();
DECLARE_EVENT_TABLE()
};
#endif

View file

@ -367,6 +367,7 @@ void FrameMain::InitMenu() {
wxMenuItem *RecentVidParent = new wxMenuItem(videoMenu, Menu_File_Recent_Vids_Parent, _("Recent"), _T(""), wxITEM_NORMAL, RecentVids); wxMenuItem *RecentVidParent = new wxMenuItem(videoMenu, Menu_File_Recent_Vids_Parent, _("Recent"), _T(""), wxITEM_NORMAL, RecentVids);
videoMenu->Append(RecentVidParent); videoMenu->Append(RecentVidParent);
videoMenu->Append(Menu_Video_Dummy, _("Use dummy video..."), _("Opens a video clip with solid colour")); videoMenu->Append(Menu_Video_Dummy, _("Use dummy video..."), _("Opens a video clip with solid colour"));
videoMenu->Append(Menu_Video_Details, _("Show video details..."), _("Shows video details"));
videoMenu->AppendSeparator(); videoMenu->AppendSeparator();
videoMenu->Append(Menu_File_Open_VFR, _("Open timecodes file..."), _("Opens a VFR timecodes v1 or v2 file")); videoMenu->Append(Menu_File_Open_VFR, _("Open timecodes file..."), _("Opens a VFR timecodes v1 or v2 file"));
videoMenu->Append(Menu_File_Close_VFR, _("Close timecodes file"), _("Closes the currently open timecodes file"))->Enable(false); videoMenu->Append(Menu_File_Close_VFR, _("Close timecodes file"), _("Closes the currently open timecodes file"))->Enable(false);

View file

@ -211,6 +211,8 @@ private:
void OnOpenResample (wxCommandEvent &event); void OnOpenResample (wxCommandEvent &event);
void OnOpenTimingProcessor (wxCommandEvent &event); void OnOpenTimingProcessor (wxCommandEvent &event);
void OnOpenKanjiTimer (wxCommandEvent &event); void OnOpenKanjiTimer (wxCommandEvent &event);
void OnOpenVideoDetails (wxCommandEvent &event);
void OnOpenOptions (wxCommandEvent &event); void OnOpenOptions (wxCommandEvent &event);
void OnOpenLog (wxCommandEvent &event); void OnOpenLog (wxCommandEvent &event);
void OnGridEvent (wxCommandEvent &event); void OnGridEvent (wxCommandEvent &event);
@ -331,6 +333,7 @@ enum {
Menu_Video_Detach, Menu_Video_Detach,
Menu_Video_Dummy, Menu_Video_Dummy,
Menu_Video_Overscan, Menu_Video_Overscan,
Menu_Video_Details,
Menu_Audio_Open_File, Menu_Audio_Open_File,
Menu_Audio_Open_From_Video, Menu_Audio_Open_From_Video,

View file

@ -83,6 +83,7 @@
#include "dialog_spellchecker.h" #include "dialog_spellchecker.h"
#include "dialog_associations.h" #include "dialog_associations.h"
#include "standard_paths.h" #include "standard_paths.h"
#include "dialog_video_details.h"
//////////////////// ////////////////////
@ -138,6 +139,7 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame)
EVT_MENU(Menu_Video_Detach, FrameMain::OnDetachVideo) EVT_MENU(Menu_Video_Detach, FrameMain::OnDetachVideo)
EVT_MENU(Menu_Video_Dummy, FrameMain::OnDummyVideo) EVT_MENU(Menu_Video_Dummy, FrameMain::OnDummyVideo)
EVT_MENU(Menu_Video_Overscan, FrameMain::OnOverscan) EVT_MENU(Menu_Video_Overscan, FrameMain::OnOverscan)
EVT_MENU(Menu_Video_Details, FrameMain::OnOpenVideoDetails)
EVT_MENU(Menu_Audio_Open_File, FrameMain::OnOpenAudio) EVT_MENU(Menu_Audio_Open_File, FrameMain::OnOpenAudio)
EVT_MENU(Menu_Audio_Open_From_Video, FrameMain::OnOpenAudioFromVideo) EVT_MENU(Menu_Audio_Open_From_Video, FrameMain::OnOpenAudioFromVideo)
@ -311,6 +313,8 @@ void FrameMain::OnMenuOpen (wxMenuEvent &event) {
MenuBar->Enable(Menu_File_Close_VFR,VFR_Output.GetFrameRateType() == VFR); MenuBar->Enable(Menu_File_Close_VFR,VFR_Output.GetFrameRateType() == VFR);
MenuBar->Enable(Menu_Video_Close_Keyframes,VideoContext::Get()->OverKeyFramesLoaded()); MenuBar->Enable(Menu_Video_Close_Keyframes,VideoContext::Get()->OverKeyFramesLoaded());
MenuBar->Enable(Menu_Video_Save_Keyframes,VideoContext::Get()->KeyFramesLoaded()); MenuBar->Enable(Menu_Video_Save_Keyframes,VideoContext::Get()->KeyFramesLoaded());
MenuBar->Enable(Menu_Video_Details,state);
MenuBar->Enable(Menu_Video_Overscan,state);
// Set AR radio // Set AR radio
int arType = VideoContext::Get()->GetAspectRatioType(); int arType = VideoContext::Get()->GetAspectRatioType();
@ -854,6 +858,15 @@ void FrameMain::OnOverscan (wxCommandEvent &event) {
} }
//////////////////////
// Show video details
void FrameMain::OnOpenVideoDetails (wxCommandEvent &event) {
VideoContext::Get()->Stop();
DialogVideoDetails videodetails(this);
videodetails.ShowModal();
}
/////////////////////// ///////////////////////
// Open jump to dialog // Open jump to dialog
void FrameMain::OnJumpTo(wxCommandEvent& WXUNUSED(event)) { void FrameMain::OnJumpTo(wxCommandEvent& WXUNUSED(event)) {

View file

@ -61,6 +61,7 @@ private:
bool usedDirectShow; bool usedDirectShow;
wxString rendererCallString; wxString rendererCallString;
wxString decoderName;
int num_frames; int num_frames;
int last_fnum; int last_fnum;
@ -100,6 +101,7 @@ public:
void OverrideFrameTimeList(wxArrayInt list); void OverrideFrameTimeList(wxArrayInt list);
bool IsNativelyByFrames() { return byFrame; } bool IsNativelyByFrames() { return byFrame; }
wxString GetWarning(); wxString GetWarning();
wxString GetDecoderName() { return _T("Avisynth/") + decoderName; }
}; };
@ -167,6 +169,7 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
byFrame = false; byFrame = false;
usedDirectShow = false; usedDirectShow = false;
decoderName = _("Unknown");
wxString extension = _filename.Right(4); wxString extension = _filename.Right(4);
extension.LowerCase(); extension.LowerCase();
@ -193,6 +196,7 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
script = env->Invoke("AviSource", AVSValue(args,2), argnames); script = env->Invoke("AviSource", AVSValue(args,2), argnames);
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened .avi file without audio")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened .avi file without audio"));
byFrame = true; byFrame = true;
decoderName = _T("AviSource");
} }
// On Failure, fallback to DSS // On Failure, fallback to DSS
@ -206,6 +210,7 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Dec3_Mpeg2Source") && mpeg2dec3_priority) { else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Dec3_Mpeg2Source") && mpeg2dec3_priority) {
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Opening .d2v file with Mpeg2Dec3_Mpeg2Source")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Opening .d2v file with Mpeg2Dec3_Mpeg2Source"));
script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename); script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename);
decoderName = _T("Mpeg2Dec3_Mpeg2Source");
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this //if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
if (env->FunctionExists("SetPlanarLegacyAlignment")) { if (env->FunctionExists("SetPlanarLegacyAlignment")) {
@ -218,6 +223,7 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
else if (extension == _T(".d2v") && env->FunctionExists("DGDecode_Mpeg2Source")) { else if (extension == _T(".d2v") && env->FunctionExists("DGDecode_Mpeg2Source")) {
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Opening .d2v file with DGDecode_Mpeg2Source")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Opening .d2v file with DGDecode_Mpeg2Source"));
script = env->Invoke("Mpeg2Source", videoFilename); script = env->Invoke("Mpeg2Source", videoFilename);
decoderName = _T("DGDecode_Mpeg2Source");
//note that DGDecode will also have issues like if the version is too ancient but no sane person //note that DGDecode will also have issues like if the version is too ancient but no sane person
//would use that anyway //would use that anyway
@ -226,6 +232,7 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Source")) { else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Source")) {
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Opening .d2v file with other Mpeg2Source")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Opening .d2v file with other Mpeg2Source"));
script = env->Invoke("Mpeg2Source", videoFilename); script = env->Invoke("Mpeg2Source", videoFilename);
decoderName = _T("Mpeg2Source");
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this //if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
if (env->FunctionExists("SetPlanarLegacyAlignment")) if (env->FunctionExists("SetPlanarLegacyAlignment"))
@ -235,7 +242,6 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
// Some other format, such as mkv, mp4, ogm... try FFMpegSource and DirectShowSource // Some other format, such as mkv, mp4, ogm... try FFMpegSource and DirectShowSource
else { else {
// Try loading FFMpegSource // Try loading FFMpegSource
directshowOpen:
bool ffsource = false; bool ffsource = false;
if (env->FunctionExists("ffmpegsource")) ffsource = true; if (env->FunctionExists("ffmpegsource")) ffsource = true;
if (!ffsource) { if (!ffsource) {
@ -255,7 +261,9 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
script = env->Invoke("ffmpegsource", videoFilename); script = env->Invoke("ffmpegsource", videoFilename);
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened file with FFMpegSource")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened file with FFMpegSource"));
ffsource = true; ffsource = true;
decoderName = _T("FFmpegSource");
} }
directshowOpen:
// DirectShowSource // DirectShowSource
if (!ffsource) { if (!ffsource) {
@ -285,6 +293,7 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
} }
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened file with DSS2")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened file with DSS2"));
dss2 = true; dss2 = true;
decoderName = _T("DSS2");
} }
// Try DirectShowSource // Try DirectShowSource
@ -302,6 +311,7 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
} }
AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened file with DSS without audio")); AVSTRACE(_T("AvisynthVideoProvider::OpenVideo: Successfully opened file with DSS without audio"));
usedDirectShow = true; usedDirectShow = true;
decoderName = _T("DirectShowSource");
} }
// Failed to find a suitable function // Failed to find a suitable function

View file

@ -121,6 +121,7 @@ public:
double GetFPS() { return fps; }; double GetFPS() { return fps; };
int GetWidth() { return width; }; int GetWidth() { return width; };
int GetHeight() { return height; }; int GetHeight() { return height; };
wxString GetDecoderName() { return _("DirectShow"); }
void OverrideFrameTimeList(wxArrayInt list); void OverrideFrameTimeList(wxArrayInt list);
}; };

View file

@ -242,3 +242,11 @@ int DummyVideoProvider::GetHeight() {
double DummyVideoProvider::GetFPS() { double DummyVideoProvider::GetFPS() {
return fps; return fps;
} }
////////////////////
// Get decoder name
wxString DummyVideoProvider::GetDecoderName() {
return _("Dummy Video Provider");
}

View file

@ -74,6 +74,7 @@ public:
int GetWidth(); int GetWidth();
int GetHeight(); int GetHeight();
double GetFPS(); double GetFPS();
wxString GetDecoderName();
}; };
#endif #endif

View file

@ -112,6 +112,7 @@ public:
int GetWidth(); int GetWidth();
int GetHeight(); int GetHeight();
double GetFPS(); double GetFPS();
wxString GetDecoderName() { return _T("FFMpeg/libavcodec")); }
bool IsNativelyByFrames() { return true; } bool IsNativelyByFrames() { return true; }
}; };