2006-01-22 13:44:53 +01:00
// Copyright (c) 2006, Fredrik Mellbin
// 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
//
2007-01-21 08:12:47 +01:00
///////////
// Headers
2009-01-04 07:31:48 +01:00
# include "config.h"
2007-01-21 07:30:19 +01:00
# include <wx/wxprec.h>
2008-01-22 03:54:16 +01:00
# ifdef WITH_AVISYNTH
2006-01-22 13:44:53 +01:00
# include <wx/filename.h>
# include <wx/msw/registry.h>
2006-12-26 02:08:46 +01:00
# include <wx/filename.h>
2008-03-05 03:05:01 +01:00
# include "video_provider_avs.h"
2007-01-21 07:30:19 +01:00
# include "video_context.h"
2006-01-22 13:44:53 +01:00
# include "options.h"
2007-06-21 02:46:50 +02:00
# include "standard_paths.h"
2007-01-01 04:29:20 +01:00
# include "vfr.h"
2007-01-21 07:30:19 +01:00
# include "ass_file.h"
2007-01-27 07:15:25 +01:00
# include "gl_wrap.h"
2008-07-15 02:08:05 +02:00
# include "mkv_wrap.h"
# include "vfw_wrap.h"
2006-01-22 13:44:53 +01:00
2006-12-19 18:30:25 +01:00
///////////////
// Constructor
2008-03-07 22:24:14 +01:00
AvisynthVideoProvider : : AvisynthVideoProvider ( Aegisub : : String _filename , double _fps ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( wxString : : Format ( _T ( " AvisynthVideoProvider: Creating new AvisynthVideoProvider: \" %s \" , \" %s \" " ) , _filename , _subfilename ) ) ;
2006-02-24 03:54:30 +01:00
bool mpeg2dec3_priority = true ;
2006-01-22 13:44:53 +01:00
RGB32Video = NULL ;
SubtitledVideo = NULL ;
2007-01-01 04:29:20 +01:00
fps = _fps ;
num_frames = 0 ;
2007-01-21 07:30:19 +01:00
last_fnum = - 1 ;
2007-07-29 11:06:38 +02:00
byFrame = false ;
2008-07-15 02:08:05 +02:00
KeyFrames . Clear ( ) ;
keyFramesLoaded = false ;
isVfr = false ;
2006-01-22 13:44:53 +01:00
2007-01-15 02:46:59 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider: Loading Subtitles Renderer " ) ) ;
LoadRenderer ( ) ;
AVSTRACE ( _T ( " AvisynthVideoProvider: Subtitles Renderer loaded " ) ) ;
2006-01-22 13:44:53 +01:00
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider: Opening video " ) ) ;
2006-02-25 21:48:32 +01:00
RGB32Video = OpenVideo ( _filename , mpeg2dec3_priority ) ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider: Video opened " ) ) ;
2006-01-22 13:44:53 +01:00
2007-01-21 07:30:19 +01:00
SubtitledVideo = RGB32Video ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider: Applied subtitles " ) ) ;
2006-03-11 17:20:40 +01:00
2007-01-21 07:30:19 +01:00
vi = SubtitledVideo - > GetVideoInfo ( ) ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider: Got video info " ) ) ;
AVSTRACE ( _T ( " AvisynthVideoProvider: Done creating AvisynthVideoProvider " ) ) ;
2006-01-22 13:44:53 +01:00
}
2006-12-19 18:30:25 +01:00
//////////////
// Destructor
2006-02-23 04:41:29 +01:00
AvisynthVideoProvider : : ~ AvisynthVideoProvider ( ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider: Destroying AvisynthVideoProvider " ) ) ;
2006-01-22 13:44:53 +01:00
RGB32Video = NULL ;
SubtitledVideo = NULL ;
2007-01-21 07:30:19 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider: Destroying frame " ) ) ;
iframe . Clear ( ) ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider: AvisynthVideoProvider destroyed " ) ) ;
2006-01-22 13:44:53 +01:00
}
2006-12-19 18:30:25 +01:00
2006-01-22 13:44:53 +01:00
2007-01-21 07:30:19 +01:00
////////////////////////////////////// VIDEO PROVIDER //////////////////////////////////////
2006-01-22 13:44:53 +01:00
2006-12-19 18:30:25 +01:00
/////////////////////////////////////////
// Actually open the video into Avisynth
2008-03-07 22:24:14 +01:00
PClip AvisynthVideoProvider : : OpenVideo ( Aegisub : : String _filename , bool mpeg2dec3_priority ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Opening video " ) ) ;
2006-01-22 13:44:53 +01:00
wxMutexLocker lock ( AviSynthMutex ) ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Got AVS mutex " ) ) ;
2006-01-22 13:44:53 +01:00
AVSValue script ;
2007-07-29 11:06:38 +02:00
byFrame = false ;
usedDirectShow = false ;
2007-08-20 00:21:41 +02:00
decoderName = _ ( " Unknown " ) ;
2006-01-22 13:44:53 +01:00
2008-03-07 22:24:14 +01:00
wxString extension = wxString ( _filename . c_str ( ) ) . Right ( 4 ) ;
2006-01-22 13:44:53 +01:00
extension . LowerCase ( ) ;
try {
// Prepare filename
2006-12-26 02:08:46 +01:00
//char *videoFilename = env->SaveString(_filename.mb_str(wxConvLocal));
wxFileName fname ( _filename ) ;
char * videoFilename = env - > SaveString ( fname . GetShortPath ( ) . mb_str ( wxConvLocal ) ) ;
2006-01-22 13:44:53 +01:00
2006-12-19 18:30:25 +01:00
// Avisynth file, just import it
2006-01-22 13:44:53 +01:00
if ( extension = = _T ( " .avs " ) ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Opening .avs file with Import " ) ) ;
2006-01-22 13:44:53 +01:00
script = env - > Invoke ( " Import " , videoFilename ) ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Finished " ) ) ;
2007-10-19 02:55:03 +02:00
decoderName = _T ( " Import " ) ;
2006-12-17 05:58:10 +01:00
}
2006-12-19 18:30:25 +01:00
// Open avi file with AviSource
2006-12-17 05:58:10 +01:00
else if ( extension = = _T ( " .avi " ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Opening .avi file with AviSource " ) ) ;
2006-01-22 13:44:53 +01:00
try {
const char * argnames [ 2 ] = { 0 , " audio " } ;
AVSValue args [ 2 ] = { videoFilename , false } ;
script = env - > Invoke ( " AviSource " , AVSValue ( args , 2 ) , argnames ) ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Successfully opened .avi file without audio " ) ) ;
2007-07-29 11:06:38 +02:00
byFrame = true ;
2007-08-20 00:21:41 +02:00
decoderName = _T ( " AviSource " ) ;
2006-12-19 18:30:25 +01:00
}
// On Failure, fallback to DSS
catch ( AvisynthError & ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " Failed to open .avi file with AviSource, switching to DirectShowSource " ) ) ;
2006-01-22 13:44:53 +01:00
goto directshowOpen ;
}
}
2006-12-19 18:30:25 +01:00
// Open d2v with mpeg2dec3
2007-01-11 20:49:37 +01:00
else if ( extension = = _T ( " .d2v " ) & & env - > FunctionExists ( " Mpeg2Dec3_Mpeg2Source " ) & & mpeg2dec3_priority ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Opening .d2v file with Mpeg2Dec3_Mpeg2Source " ) ) ;
script = env - > Invoke ( " Mpeg2Dec3_Mpeg2Source " , videoFilename ) ;
2007-08-20 00:21:41 +02:00
decoderName = _T ( " Mpeg2Dec3_Mpeg2Source " ) ;
2007-01-11 20:49:37 +01:00
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
2007-01-15 21:48:58 +01:00
if ( env - > FunctionExists ( " SetPlanarLegacyAlignment " ) ) {
AVSValue args [ 2 ] = { script , true } ;
script = env - > Invoke ( " SetPlanarLegacyAlignment " , AVSValue ( args , 2 ) ) ;
}
2007-01-11 20:49:37 +01:00
}
// If that fails, try opening it with DGDecode
else if ( extension = = _T ( " .d2v " ) & & env - > FunctionExists ( " DGDecode_Mpeg2Source " ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Opening .d2v file with DGDecode_Mpeg2Source " ) ) ;
script = env - > Invoke ( " Mpeg2Source " , videoFilename ) ;
2007-08-20 00:21:41 +02:00
decoderName = _T ( " DGDecode_Mpeg2Source " ) ;
2007-01-11 20:49:37 +01:00
//note that DGDecode will also have issues like if the version is too ancient but no sane person
//would use that anyway
2006-12-17 05:58:10 +01:00
}
2006-12-19 18:30:25 +01:00
else if ( extension = = _T ( " .d2v " ) & & env - > FunctionExists ( " Mpeg2Source " ) ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Opening .d2v file with other Mpeg2Source " ) ) ;
2006-01-22 13:44:53 +01:00
script = env - > Invoke ( " Mpeg2Source " , videoFilename ) ;
2007-08-20 00:21:41 +02:00
decoderName = _T ( " Mpeg2Source " ) ;
2007-01-11 20:49:37 +01:00
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
if ( env - > FunctionExists ( " SetPlanarLegacyAlignment " ) )
script = env - > Invoke ( " SetPlanarLegacyAlignment " , script ) ;
2006-12-17 05:58:10 +01:00
}
2006-12-19 18:30:25 +01:00
2007-06-17 00:07:43 +02:00
// Some other format, such as mkv, mp4, ogm... try FFMpegSource and DirectShowSource
2006-01-22 13:44:53 +01:00
else {
2007-06-17 00:07:43 +02:00
// Try loading FFMpegSource
2007-08-20 00:56:22 +02:00
directshowOpen :
2007-06-17 00:07:43 +02:00
bool ffsource = false ;
if ( env - > FunctionExists ( " ffmpegsource " ) ) ffsource = true ;
if ( ! ffsource ) {
2007-06-21 02:46:50 +02:00
wxFileName ffsourcepath ( StandardPaths : : DecodePath ( _T ( " ?data/ffmpegsource.dll " ) ) ) ;
2007-06-17 00:07:43 +02:00
if ( ffsourcepath . FileExists ( ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Loading FFMpegSource " ) ) ;
env - > Invoke ( " LoadPlugin " , env - > SaveString ( ffsourcepath . GetFullPath ( ) . mb_str ( wxConvLocal ) ) ) ;
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Loaded FFMpegSource " ) ) ;
2007-07-29 11:06:38 +02:00
byFrame = true ;
2006-12-19 18:30:25 +01:00
}
2006-12-17 05:58:10 +01:00
}
2006-12-19 18:30:25 +01:00
2007-06-17 00:07:43 +02:00
// If FFMpegSource loaded properly, try using it
ffsource = false ;
if ( env - > FunctionExists ( " ffmpegsource " ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Invoking FFMpegSource " ) ) ;
2007-10-18 22:19:06 +02:00
const char * argnames [ 2 ] = { " source " , " vcache " } ;
AVSValue args [ 2 ] = { videoFilename , false } ;
script = env - > Invoke ( " ffmpegsource " , AVSValue ( args , 2 ) , argnames ) ;
//script = env->Invoke("ffmpegsource", videoFilename);
2007-06-17 00:07:43 +02:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Successfully opened file with FFMpegSource " ) ) ;
ffsource = true ;
2007-08-20 00:21:41 +02:00
decoderName = _T ( " FFmpegSource " ) ;
2006-12-17 05:58:10 +01:00
}
2006-12-19 18:30:25 +01:00
2007-06-17 00:07:43 +02:00
// DirectShowSource
if ( ! ffsource ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Opening file with DirectShowSource " ) ) ;
// Try loading DirectShowSource2
bool dss2 = false ;
if ( env - > FunctionExists ( " dss2 " ) ) dss2 = true ;
if ( ! dss2 ) {
2007-06-21 02:46:50 +02:00
wxFileName dss2path ( StandardPaths : : DecodePath ( _T ( " ?data/avss.dll " ) ) ) ;
2007-06-17 00:07:43 +02:00
if ( dss2path . FileExists ( ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Loading DirectShowSource2 " ) ) ;
env - > Invoke ( " LoadPlugin " , env - > SaveString ( dss2path . GetFullPath ( ) . mb_str ( wxConvLocal ) ) ) ;
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Loaded DirectShowSource2 " ) ) ;
2007-01-01 04:34:08 +01:00
}
2007-06-17 00:07:43 +02:00
}
// If DSS2 loaded properly, try using it
dss2 = false ;
if ( env - > FunctionExists ( " dss2 " ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Invoking DSS2 " ) ) ;
if ( fps = = 0.0 ) script = env - > Invoke ( " DSS2 " , videoFilename ) ;
2007-01-01 04:34:08 +01:00
else {
2007-06-17 00:07:43 +02:00
const char * argnames [ 2 ] = { 0 , " fps " } ;
AVSValue args [ 2 ] = { videoFilename , fps } ;
script = env - > Invoke ( " DSS2 " , AVSValue ( args , 2 ) , argnames ) ;
2007-01-01 04:34:08 +01:00
}
2007-06-17 00:07:43 +02:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Successfully opened file with DSS2 " ) ) ;
dss2 = true ;
2007-08-20 00:21:41 +02:00
decoderName = _T ( " DSS2 " ) ;
2006-12-19 18:30:25 +01:00
}
2007-06-17 00:07:43 +02:00
// Try DirectShowSource
if ( ! dss2 ) {
2007-08-28 23:34:44 +02:00
// Load DirectShowSource.dll from app dir if it exists
wxFileName dsspath ( StandardPaths : : DecodePath ( _T ( " ?data/DirectShowSource.dll " ) ) ) ;
if ( dsspath . FileExists ( ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Loading DirectShowSource " ) ) ;
env - > Invoke ( " LoadPlugin " , env - > SaveString ( dsspath . GetFullPath ( ) . mb_str ( wxConvLocal ) ) ) ;
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Loaded DirectShowSource " ) ) ;
}
// Then try using DSS
2007-06-17 00:07:43 +02:00
if ( env - > FunctionExists ( " DirectShowSource " ) ) {
if ( fps = = 0.0 ) {
const char * argnames [ 3 ] = { 0 , " video " , " audio " } ;
AVSValue args [ 3 ] = { videoFilename , true , false } ;
script = env - > Invoke ( " DirectShowSource " , AVSValue ( args , 3 ) , argnames ) ;
}
else {
const char * argnames [ 4 ] = { 0 , " video " , " audio " , " fps " } ;
AVSValue args [ 4 ] = { videoFilename , true , false , fps } ;
script = env - > Invoke ( " DirectShowSource " , AVSValue ( args , 4 ) , argnames ) ;
}
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Successfully opened file with DSS without audio " ) ) ;
2007-07-29 11:06:38 +02:00
usedDirectShow = true ;
2007-08-20 00:21:41 +02:00
decoderName = _T ( " DirectShowSource " ) ;
2007-06-17 00:07:43 +02:00
}
// Failed to find a suitable function
else {
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: DSS function not found " ) ) ;
throw AvisynthError ( " No function suitable for opening the video found " ) ;
}
2006-12-19 18:30:25 +01:00
}
}
}
}
// Catch errors
catch ( AvisynthError & err ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Avisynth error: " ) + wxString ( err . msg , wxConvLocal ) ) ;
2006-01-22 13:44:53 +01:00
throw _T ( " AviSynth error: " ) + wxString ( err . msg , wxConvLocal ) ;
}
2006-12-19 18:30:25 +01:00
// Check if video was loaded properly
2008-03-06 22:38:40 +01:00
if ( ! script . IsClip ( ) | | ! script . AsClip ( ) - > GetVideoInfo ( ) . HasVideo ( ) ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: No suitable video found " ) ) ;
2007-07-18 15:46:38 +02:00
throw _T ( " Avisynth: No usable video found in " ) + _filename ;
2006-12-17 05:58:10 +01:00
}
2006-01-22 13:44:53 +01:00
2008-07-15 02:08:05 +02:00
// Read keyframes and timecodes from MKV file
isVfr = false ;
FrameRate temp ;
double overFps = 0 ;
bool mkvOpen = MatroskaWrapper : : wrapper . IsOpen ( ) ;
KeyFrames . Clear ( ) ;
if ( extension = = _T ( " .mkv " ) | | mkvOpen ) {
// Parse mkv
if ( ! mkvOpen ) MatroskaWrapper : : wrapper . Open ( _filename ) ;
// Get keyframes
KeyFrames = MatroskaWrapper : : wrapper . GetKeyFrames ( ) ;
keyFramesLoaded = true ;
// 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 ( temp ) ;
isVfr = temp . GetFrameRateType ( ) = = VFR ;
if ( isVfr ) {
overFps = temp . GetCommonFPS ( ) ;
MatroskaWrapper : : wrapper . SetToTimecodes ( VFR_Input ) ;
MatroskaWrapper : : wrapper . SetToTimecodes ( VFR_Output ) ;
trueFrameRate = temp ;
}
}
// Close mkv
MatroskaWrapper : : wrapper . Close ( ) ;
}
// check if we have windows, if so we can load keyframes from AVI files using VFW
# ifdef __WINDOWS__
else if ( extension = = _T ( " .avi " ) ) {
keyFramesLoaded = false ;
KeyFrames . Clear ( ) ;
KeyFrames = VFWWrapper : : GetKeyFrames ( _filename ) ;
keyFramesLoaded = true ;
}
# endif /* __WINDOWS__ */
// Check if the file is all keyframes
bool isAllKeyFrames = true ;
for ( unsigned int i = 1 ; i < KeyFrames . GetCount ( ) ; i + + ) {
// Is the last keyframe not this keyframe -1?
if ( KeyFrames [ i - 1 ] ! = ( int ) ( i - 1 ) ) {
// It's not all keyframes, go ahead
isAllKeyFrames = false ;
break ;
}
}
// If it is all keyframes, discard the keyframe info as it is useless
if ( isAllKeyFrames ) {
KeyFrames . Clear ( ) ;
keyFramesLoaded = false ;
}
2006-01-22 13:44:53 +01:00
// Convert to RGB32
2007-08-31 16:11:35 +02:00
// If "Avisynth renders its own subs" is enabled, this should always be done,
// regardless of shaders being enabled or not. (Since VSFilter will convert
// to RGB32 and back again itself either way.)
2007-01-27 08:13:29 +01:00
if ( ! OpenGLWrapper : : UseShaders ( ) ) {
2007-01-27 07:15:25 +01:00
script = env - > Invoke ( " ConvertToRGB32 " , script ) ;
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Converted to RGB32 " ) ) ;
}
2006-01-22 13:44:53 +01:00
// Cache
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::OpenVideo: Finished opening video, AVS mutex will be released now " ) ) ;
2006-02-22 20:47:44 +01:00
return ( env - > Invoke ( " Cache " , script ) ) . AsClip ( ) ;
2006-01-22 13:44:53 +01:00
}
2006-12-19 18:30:25 +01:00
2007-01-21 07:30:19 +01:00
////////////////////////
// Actually get a frame
2008-03-06 20:20:25 +01:00
const AegiVideoFrame AvisynthVideoProvider : : GetFrame ( int _n , int formatMask ) {
2007-01-21 07:30:19 +01:00
// 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 avs frame
AVSTRACE ( _T ( " AvisynthVideoProvider::GetFrame " ) ) ;
wxMutexLocker lock ( AviSynthMutex ) ;
PVideoFrame frame = SubtitledVideo - > GetFrame ( n , env ) ;
int Bpp = vi . BitsPerPixel ( ) / 8 ;
// Aegisub's video frame
AegiVideoFrame & final = iframe ;
final . flipped = false ;
final . cppAlloc = true ;
2007-01-29 06:47:29 +01:00
final . invertChannels = false ;
2007-01-21 07:30:19 +01:00
// Format
if ( vi . IsRGB32 ( ) ) {
final . format = FORMAT_RGB32 ;
final . flipped = true ;
2007-01-29 06:47:29 +01:00
final . invertChannels = true ;
2007-01-21 07:30:19 +01:00
}
else if ( vi . IsRGB24 ( ) ) {
final . format = FORMAT_RGB24 ;
final . flipped = true ;
2007-01-29 06:47:29 +01:00
final . invertChannels = true ;
2007-01-21 07:30:19 +01:00
}
else if ( vi . IsYV12 ( ) ) final . format = FORMAT_YV12 ;
else if ( vi . IsYUY2 ( ) ) final . format = FORMAT_YUY2 ;
// Set size properties
int uvpitch = 0 ;
if ( final . format = = FORMAT_YV12 ) uvpitch = frame - > GetPitch ( PLANAR_U ) ;
final . pitch [ 0 ] = frame - > GetPitch ( ) ;
final . pitch [ 1 ] = uvpitch ;
final . pitch [ 2 ] = uvpitch ;
final . w = frame - > GetRowSize ( ) / Bpp ;
final . h = frame - > GetHeight ( ) ;
// Allocate
final . Allocate ( ) ;
// Copy
memcpy ( final . data [ 0 ] , frame - > GetReadPtr ( ) , final . pitch [ 0 ] * final . h ) ;
// Copy second and third planes for YV12
if ( final . format = = FORMAT_YV12 ) {
int uvh = frame - > GetHeight ( PLANAR_U ) ;
memcpy ( final . data [ 1 ] , frame - > GetReadPtr ( PLANAR_U ) , uvpitch * uvh ) ;
memcpy ( final . data [ 2 ] , frame - > GetReadPtr ( PLANAR_V ) , uvpitch * uvh ) ;
}
// Set last number
last_fnum = n ;
return final ;
}
2006-12-19 18:30:25 +01:00
////////////////////////////////////////////////////////
// Apply VSFilter subtitles, or whatever is appropriate
2008-03-07 22:24:14 +01:00
PClip AvisynthVideoProvider : : ApplySubtitles ( Aegisub : : String _filename , PClip videosource ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::ApplySutitles: Applying subtitles " ) ) ;
2006-01-22 13:44:53 +01:00
wxMutexLocker lock ( AviSynthMutex ) ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::ApplySutitles: Got AVS mutex " ) ) ;
2006-01-22 13:44:53 +01:00
// Insert subs
AVSValue script ;
char temp [ 512 ] ;
2006-12-26 02:08:46 +01:00
wxFileName fname ( _filename ) ;
strcpy ( temp , fname . GetShortPath ( ) . mb_str ( wxConvLocal ) ) ;
2006-01-22 13:44:53 +01:00
AVSValue args [ 2 ] = { videosource , temp } ;
try {
2007-01-15 02:46:59 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::ApplySutitles: Now invoking " ) + rendererCallString ) ;
2008-03-07 22:24:14 +01:00
script = env - > Invoke ( wxString ( rendererCallString . c_str ( ) ) . mb_str ( wxConvUTF8 ) , AVSValue ( args , 2 ) ) ;
2007-01-15 02:46:59 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::ApplySutitles: Invoked successfully " ) ) ;
}
catch ( AvisynthError & err ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::ApplySutitles: Avisynth error: " ) + wxString ( err . msg , wxConvLocal ) ) ;
2006-01-22 13:44:53 +01:00
throw _T ( " AviSynth error: " ) + wxString ( err . msg , wxConvLocal ) ;
}
// Cache
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::ApplySutitles: Subtitles applied, AVS mutex will be released now " ) ) ;
2006-02-22 20:47:44 +01:00
return ( env - > Invoke ( " Cache " , script ) ) . AsClip ( ) ;
2006-01-22 13:44:53 +01:00
}
2006-12-19 18:30:25 +01:00
2006-01-22 13:44:53 +01:00
2007-01-21 07:30:19 +01:00
////////////////////////////////////// SUBTITLES PROVIDER //////////////////////////////////////
2006-01-22 13:44:53 +01:00
2007-01-21 07:30:19 +01:00
/////////////////////////////
// Get as subtitles provider
SubtitlesProvider * AvisynthVideoProvider : : GetAsSubtitlesProvider ( ) {
2007-04-08 21:27:46 +02:00
if ( Options . AsBool ( _T ( " Avisynth render own subs " ) ) ) return this ;
return NULL ;
2006-01-22 13:44:53 +01:00
}
2006-12-19 18:30:25 +01:00
2007-01-21 07:30:19 +01:00
/////////////////////
// Refresh subtitles
void AvisynthVideoProvider : : LoadSubtitles ( AssFile * subs ) {
// Reset
AVSTRACE ( _T ( " AvisynthVideoProvider::RefreshSubtitles: Refreshing subtitles " ) ) ;
SubtitledVideo = NULL ;
2006-01-28 20:48:35 +01:00
2007-01-21 07:30:19 +01:00
// Dump subs to disk
wxString subfilename = VideoContext : : Get ( ) - > GetTempWorkFile ( ) ;
subs - > Save ( subfilename , false , false , _T ( " UTF-8 " ) ) ;
delete subs ;
2006-01-28 20:48:35 +01:00
2007-01-21 07:30:19 +01:00
// Load subtitles
2008-03-07 22:24:14 +01:00
SubtitledVideo = ApplySubtitles ( subfilename . c_str ( ) , RGB32Video ) ;
2007-01-21 07:30:19 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::RefreshSubtitles: Subtitles refreshed " ) ) ;
vi = SubtitledVideo - > GetVideoInfo ( ) ;
AVSTRACE ( _T ( " AvisynthVideoProvider: Got video info " ) ) ;
2006-01-28 20:48:35 +01:00
}
2006-12-19 18:30:25 +01:00
2007-01-15 02:46:59 +01:00
/////////////////////////////
// Load appropriate renderer
void AvisynthVideoProvider : : LoadRenderer ( ) {
// Get prefferred
wxString prefferred = Options . AsText ( _T ( " Avisynth subs renderer " ) ) ;
// Load
if ( prefferred . Lower ( ) = = _T ( " asa " ) ) LoadASA ( ) ;
else LoadVSFilter ( ) ;
}
2006-12-19 18:30:25 +01:00
/////////////////
// Load VSFilter
2006-02-23 04:41:29 +01:00
void AvisynthVideoProvider : : LoadVSFilter ( ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadVSFilter: Loading VSFilter " ) ) ;
2006-01-22 13:44:53 +01:00
// Loading an avisynth plugin multiple times does almost nothing
2007-10-13 04:13:51 +02:00
wxFileName vsfilterPath ( StandardPaths : : DecodePath ( _T ( " ?data/csri/vsfilter.dll " ) ) ) ;
if ( ! vsfilterPath . FileExists ( ) )
vsfilterPath = wxFileName ( StandardPaths : : DecodePath ( _T ( " ?data/vsfilter.dll " ) ) ) ;
2007-01-15 02:46:59 +01:00
rendererCallString = _T ( " TextSub " ) ;
2006-01-22 13:44:53 +01:00
2006-12-17 05:58:10 +01:00
if ( vsfilterPath . FileExists ( ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadVSFilter: Invoking LoadPlugin " ) ) ;
2006-01-22 13:44:53 +01:00
env - > Invoke ( " LoadPlugin " , env - > SaveString ( vsfilterPath . GetFullPath ( ) . mb_str ( wxConvLocal ) ) ) ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadVSFilter: Loaded " ) ) ;
2007-01-15 02:46:59 +01:00
}
else {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadVSFilter: VSFilter.dll not found in Aegisub dir, trying to locate registered DShow filter " ) ) ;
2006-01-22 13:44:53 +01:00
wxRegKey reg ( _T ( " HKEY_CLASSES_ROOT \\ CLSID \\ {9852A670-F845-491B-9BE6-EBD841B8A613} \\ InprocServer32 " ) ) ;
if ( reg . Exists ( ) ) {
wxString fn ;
reg . QueryValue ( _T ( " " ) , fn ) ;
vsfilterPath = fn ;
if ( vsfilterPath . FileExists ( ) ) {
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadVSFilter: Found as DShow filter, loading " ) ) ;
2006-01-22 13:44:53 +01:00
env - > Invoke ( " LoadPlugin " , env - > SaveString ( vsfilterPath . GetFullPath ( ) . mb_str ( wxConvLocal ) ) ) ;
2006-12-17 05:58:10 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadVSFilter: Loaded " ) ) ;
2006-01-22 13:44:53 +01:00
return ;
}
vsfilterPath = _T ( " vsfilter.dll " ) ;
2007-01-15 02:46:59 +01:00
}
else if ( vsfilterPath . FileExists ( ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadVSFilter: Found on system path, loading " ) ) ;
2006-01-22 13:44:53 +01:00
env - > Invoke ( " LoadPlugin " , env - > SaveString ( vsfilterPath . GetFullPath ( ) . mb_str ( wxConvLocal ) ) ) ;
2007-01-15 02:46:59 +01:00
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadVSFilter: Loaded " ) ) ;
}
2006-12-17 05:58:10 +01:00
else if ( ! env - > FunctionExists ( " TextSub " ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadVSFilter: Couldn't locate VSFilter " ) ) ;
2007-07-18 15:46:38 +02:00
throw _T ( " Couldn't locate VSFilter for Avisynth internal subtitle rendering " ) ;
2006-12-17 05:58:10 +01:00
}
2006-01-22 13:44:53 +01:00
}
}
2006-02-24 09:30:08 +01:00
2007-01-15 02:46:59 +01:00
////////////
// Load asa
void AvisynthVideoProvider : : LoadASA ( ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadASA: Loading asa " ) ) ;
// Loading an avisynth plugin multiple times does almost nothing
2007-06-21 02:46:50 +02:00
wxFileName asaPath ( StandardPaths : : DecodePath ( _T ( " ?data/asa.dll " ) ) ) ;
2007-01-15 02:46:59 +01:00
rendererCallString = _T ( " asa " ) ;
if ( asaPath . FileExists ( ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadASA: Invoking LoadPlugin " ) ) ;
env - > Invoke ( " LoadPlugin " , env - > SaveString ( asaPath . GetFullPath ( ) . mb_str ( wxConvLocal ) ) ) ;
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadASA: Loaded " ) ) ;
}
else {
asaPath = _T ( " asa.dll " ) ;
if ( asaPath . FileExists ( ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadASA: Invoking LoadPlugin " ) ) ;
env - > Invoke ( " LoadPlugin " , env - > SaveString ( asaPath . GetFullPath ( ) . mb_str ( wxConvLocal ) ) ) ;
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadASA: Loaded " ) ) ;
}
else if ( ! env - > FunctionExists ( " asa " ) ) {
AVSTRACE ( _T ( " AvisynthVideoProvider::LoadASA: Couldn't locate asa " ) ) ;
2007-07-18 15:46:38 +02:00
throw _T ( " Couldn't locate asa for Avisynth internal subtitle rendering " ) ;
2007-01-15 02:46:59 +01:00
}
}
}
2007-01-01 04:29:20 +01:00
////////////////////////
// Override frame times
void AvisynthVideoProvider : : OverrideFrameTimeList ( wxArrayInt list ) {
frameTime = list ;
num_frames = frameTime . Count ( ) ;
}
2007-01-23 05:42:08 +01:00
2007-07-29 11:06:38 +02:00
///////////////
// Get warning
2008-03-07 22:24:14 +01:00
Aegisub : : String AvisynthVideoProvider : : GetWarning ( ) {
if ( usedDirectShow ) return L " Warning! The file is being opened using Avisynth's DirectShowSource, which has unreliable seeking. Frame numbers might not match the real number. PROCEED AT YOUR OWN RISK! " ;
else return L " " ;
2007-07-29 11:06:38 +02:00
}
2007-01-23 05:42:08 +01:00
# endif