2007-01-21 07:30:19 +01:00
// Copyright (c) 2005-2007, Rodrigo Braz Monteiro
// 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.
//
2009-07-29 07:43:02 +02:00
// Aegisub Project http://www.aegisub.org/
/// @file video_context.cpp
2010-12-07 20:09:28 +01:00
/// @brief Keep track of loaded video
2009-07-29 07:43:02 +02:00
/// @ingroup video
///
2007-01-21 07:30:19 +01:00
2009-01-04 07:31:48 +01:00
# include "config.h"
2013-01-04 16:01:50 +01:00
# include "video_context.h"
2011-01-16 08:17:08 +01:00
2007-01-21 07:30:19 +01:00
# include "ass_dialogue.h"
2009-09-10 15:06:40 +02:00
# include "ass_file.h"
# include "ass_time.h"
2010-12-08 04:36:10 +01:00
# include "audio_controller.h"
2010-05-21 03:13:36 +02:00
# include "compat.h"
2011-01-16 08:17:08 +01:00
# include "include/aegisub/context.h"
2010-07-23 07:58:39 +02:00
# include "include/aegisub/video_provider.h"
2010-05-19 02:44:37 +02:00
# include "mkv_wrap.h"
2013-01-07 02:50:09 +01:00
# include "options.h"
2010-12-08 04:36:10 +01:00
# include "selection_controller.h"
2013-01-26 02:57:46 +01:00
# include "subs_controller.h"
2012-02-02 00:59:12 +01:00
# include "time_range.h"
2010-07-23 07:58:39 +02:00
# include "threaded_frame_source.h"
2009-09-10 15:06:40 +02:00
# include "utils.h"
2010-08-02 08:32:01 +02:00
# include "video_frame.h"
2007-01-21 07:30:19 +01:00
2013-01-04 16:01:50 +01:00
# include <libaegisub/fs.h>
# include <libaegisub/keyframe.h>
# include <libaegisub/path.h>
# include <wx/msgdlg.h>
2010-05-19 02:44:37 +02:00
VideoContext : : VideoContext ( )
2011-12-05 06:26:45 +01:00
: playback ( this )
2010-06-11 04:24:59 +02:00
, playAudioOnStep ( OPT_GET ( " Audio/Plays When Stepping Video " ) )
2010-05-19 02:44:37 +02:00
{
2010-07-23 07:58:39 +02:00
Bind ( EVT_VIDEO_ERROR , & VideoContext : : OnVideoError , this ) ;
Bind ( EVT_SUBTITLES_ERROR , & VideoContext : : OnSubtitlesError , this ) ;
2011-12-05 06:26:45 +01:00
Bind ( wxEVT_TIMER , & VideoContext : : OnPlayTimer , this ) ;
2010-08-26 20:38:37 +02:00
2010-12-07 20:09:15 +01:00
OPT_SUB ( " Subtitle/Provider " , & VideoContext : : Reload , this ) ;
OPT_SUB ( " Video/Provider " , & VideoContext : : Reload , this ) ;
2010-08-26 20:38:37 +02:00
// It would be nice to find a way to move these to the individual providers
2010-12-07 20:09:15 +01:00
OPT_SUB ( " Provider/Avisynth/Allow Ancient " , & VideoContext : : Reload , this ) ;
OPT_SUB ( " Provider/Avisynth/Memory Max " , & VideoContext : : Reload , this ) ;
2010-08-26 20:38:37 +02:00
2010-12-07 20:09:15 +01:00
OPT_SUB ( " Provider/Video/FFmpegSource/Decoding Threads " , & VideoContext : : Reload , this ) ;
OPT_SUB ( " Provider/Video/FFmpegSource/Unsafe Seeking " , & VideoContext : : Reload , this ) ;
2012-04-17 17:03:27 +02:00
OPT_SUB ( " Video/Force BT.601 " , & VideoContext : : Reload , this ) ;
2007-01-21 07:30:19 +01:00
}
VideoContext : : ~ VideoContext ( ) {
}
VideoContext * VideoContext : : Get ( ) {
2010-07-08 06:29:04 +02:00
static VideoContext instance ;
return & instance ;
2007-01-21 07:30:19 +01:00
}
void VideoContext : : Reset ( ) {
2013-01-04 16:01:50 +01:00
config : : path - > SetToken ( " ?video " , " " ) ;
2007-06-21 00:23:55 +02:00
2007-01-21 07:30:19 +01:00
// Remove video data
2011-12-05 06:26:45 +01:00
Stop ( ) ;
2007-01-21 07:30:19 +01:00
frame_n = 0 ;
// Clean up video data
2013-01-04 16:01:50 +01:00
video_filename . clear ( ) ;
2007-01-21 07:30:19 +01:00
// Remove provider
2010-07-08 06:29:04 +02:00
provider . reset ( ) ;
2013-02-09 06:04:19 +01:00
video_provider = nullptr ;
2011-12-22 22:29:38 +01:00
2013-01-04 16:01:50 +01:00
keyframes . clear ( ) ;
keyframes_filename . clear ( ) ;
video_fps = agi : : vfr : : Framerate ( ) ;
KeyframesOpen ( keyframes ) ;
if ( ! ovr_fps . IsLoaded ( ) ) TimecodesOpen ( video_fps ) ;
2007-04-08 21:27:46 +02:00
}
2011-01-16 08:17:08 +01:00
void VideoContext : : SetContext ( agi : : Context * context ) {
this - > context = context ;
context - > ass - > AddCommitListener ( & VideoContext : : OnSubtitlesCommit , this ) ;
2013-01-26 02:57:46 +01:00
context - > subsController - > AddFileSaveListener ( & VideoContext : : OnSubtitlesSave , this ) ;
2011-01-16 08:17:08 +01:00
}
2013-01-04 16:01:50 +01:00
void VideoContext : : SetVideo ( const agi : : fs : : path & filename ) {
2007-01-21 07:30:19 +01:00
Reset ( ) ;
2011-01-16 08:16:27 +01:00
if ( filename . empty ( ) ) {
VideoOpen ( ) ;
return ;
}
2009-10-06 18:12:23 +02:00
2012-04-02 06:22:22 +02:00
bool commit_subs = false ;
2010-07-08 06:29:04 +02:00
try {
2013-10-17 16:23:45 +02:00
provider . reset ( new ThreadedFrameSource ( filename , context - > ass - > GetScriptInfo ( " YCbCr Matrix " ) , this ) ) ;
2013-01-04 16:01:50 +01:00
video_provider = provider - > GetVideoProvider ( ) ;
video_filename = filename ;
2010-07-08 06:29:04 +02:00
2011-11-28 23:16:22 +01:00
// Check that the script resolution matches the video resolution
int sx = context - > ass - > GetScriptInfoAsInt ( " PlayResX " ) ;
int sy = context - > ass - > GetScriptInfoAsInt ( " PlayResY " ) ;
int vx = GetWidth ( ) ;
int vy = GetHeight ( ) ;
// If the script resolution hasn't been set at all just force it to the
// video resolution
if ( sx = = 0 & & sy = = 0 ) {
2013-01-04 16:01:50 +01:00
context - > ass - > SetScriptInfo ( " PlayResX " , std : : to_string ( vx ) ) ;
context - > ass - > SetScriptInfo ( " PlayResY " , std : : to_string ( vy ) ) ;
2012-04-02 06:22:22 +02:00
commit_subs = true ;
2011-11-28 23:16:22 +01:00
}
// If it has been set to something other than a multiple of the video
// resolution, ask the user if they want it to be fixed
else if ( sx % vx ! = 0 | | sy % vy ! = 0 ) {
switch ( OPT_GET ( " Video/Check Script Res " ) - > GetInt ( ) ) {
case 1 : // Ask to change on mismatch
2012-03-29 01:59:19 +02:00
if ( wxYES ! = wxMessageBox (
wxString : : Format ( _ ( " The resolution of the loaded video and the resolution specified for the subtitles don't match. \n \n Video resolution: \t %d x %d \n Script resolution: \t %d x %d \n \n Change subtitles resolution to match video? " ) , vx , vy , sx , sy ) ,
_ ( " Resolution mismatch " ) ,
wxYES_NO | wxCENTER ,
context - > parent ) )
2011-11-28 23:16:22 +01:00
break ;
// Fallthrough to case 2
case 2 : // Always change script res
2013-01-04 16:01:50 +01:00
context - > ass - > SetScriptInfo ( " PlayResX " , std : : to_string ( vx ) ) ;
context - > ass - > SetScriptInfo ( " PlayResY " , std : : to_string ( vy ) ) ;
2012-04-02 06:22:22 +02:00
commit_subs = true ;
2011-11-28 23:16:22 +01:00
break ;
default : // Never change
break ;
}
}
2013-01-04 16:01:50 +01:00
keyframes = video_provider - > GetKeyFrames ( ) ;
2010-07-08 06:29:04 +02:00
// Set frame rate
2013-01-04 16:01:50 +01:00
video_fps = video_provider - > GetFPS ( ) ;
if ( ovr_fps . IsLoaded ( ) ) {
2010-07-08 06:29:04 +02:00
int ovr = wxMessageBox ( _ ( " You already have timecodes loaded. Would you like to replace them with timecodes from the video file? " ) , _ ( " Replace timecodes? " ) , wxYES_NO | wxICON_QUESTION ) ;
if ( ovr = = wxYES ) {
2013-01-04 16:01:50 +01:00
ovr_fps = agi : : vfr : : Framerate ( ) ;
timecodes_filename . clear ( ) ;
2009-06-24 20:16:03 +02:00
}
2010-07-08 06:29:04 +02:00
}
2007-01-21 07:30:19 +01:00
2012-02-23 02:30:59 +01:00
// Set aspect ratio
2013-01-04 16:01:50 +01:00
double dar = video_provider - > GetDAR ( ) ;
2012-02-23 02:30:59 +01:00
if ( dar > 0 )
2013-01-20 22:05:24 +01:00
SetAspectRatio ( dar ) ;
2012-02-23 02:30:59 +01:00
2010-07-08 06:29:04 +02:00
// Set filename
2013-01-04 16:01:50 +01:00
config : : mru - > Add ( " Video " , filename ) ;
config : : path - > SetToken ( " ?video " , filename ) ;
2007-07-29 11:06:38 +02:00
2010-07-08 06:29:04 +02:00
// Show warning
2013-01-04 16:01:50 +01:00
std : : string warning = video_provider - > GetWarning ( ) ;
if ( ! warning . empty ( ) )
wxMessageBox ( to_wx ( warning ) , " Warning " , wxICON_WARNING | wxOK ) ;
2010-05-19 02:44:37 +02:00
2013-01-04 16:01:50 +01:00
has_subtitles = false ;
if ( agi : : fs : : HasExtension ( filename , " mkv " ) )
has_subtitles = MatroskaWrapper : : HasSubtitles ( filename ) ;
2010-07-08 06:29:04 +02:00
2011-01-16 08:17:08 +01:00
provider - > LoadSubtitles ( context - > ass ) ;
2010-12-07 20:09:21 +01:00
VideoOpen ( ) ;
2013-01-04 16:01:50 +01:00
KeyframesOpen ( keyframes ) ;
2010-12-31 22:03:18 +01:00
TimecodesOpen ( FPS ( ) ) ;
2010-07-08 06:29:04 +02:00
}
2010-08-02 08:32:01 +02:00
catch ( agi : : UserCancelException const & ) { }
2013-01-04 16:01:50 +01:00
catch ( agi : : fs : : FileSystemError const & err ) {
config : : mru - > Remove ( " Video " , filename ) ;
2012-12-23 00:18:38 +01:00
wxMessageBox ( to_wx ( err . GetMessage ( ) ) , " Error setting video " , wxOK | wxICON_ERROR | wxCENTER ) ;
2010-07-23 08:40:12 +02:00
}
2010-08-02 08:32:01 +02:00
catch ( VideoProviderError const & err ) {
2012-12-23 00:18:38 +01:00
wxMessageBox ( to_wx ( err . GetMessage ( ) ) , " Error setting video " , wxOK | wxICON_ERROR | wxCENTER ) ;
2007-01-21 07:30:19 +01:00
}
2012-04-02 06:22:22 +02:00
if ( commit_subs )
context - > ass - > Commit ( _ ( " change script resolution " ) , AssFile : : COMMIT_SCRIPTINFO ) ;
2012-04-03 19:38:38 +02:00
else
JumpToFrame ( 0 ) ;
2007-01-21 07:30:19 +01:00
}
2010-08-26 20:38:37 +02:00
void VideoContext : : Reload ( ) {
if ( IsLoaded ( ) ) {
int frame = frame_n ;
2013-01-04 16:01:50 +01:00
SetVideo ( agi : : fs : : path ( video_filename ) ) ; // explicitly copy videoFile since it's cleared in SetVideo
2010-08-26 20:38:37 +02:00
JumpToFrame ( frame ) ;
}
}
2012-12-17 17:27:11 +01:00
void VideoContext : : OnSubtitlesCommit ( int type , std : : set < const AssEntry * > const & changed ) {
2010-07-23 07:58:39 +02:00
if ( ! IsLoaded ( ) ) return ;
2010-07-20 05:11:11 +02:00
2013-01-14 17:15:12 +01:00
if ( changed . empty ( ) | | no_amend )
2012-12-17 17:27:11 +01:00
provider - > LoadSubtitles ( context - > ass ) ;
else
provider - > UpdateSubtitles ( context - > ass , changed ) ;
2011-12-27 02:38:00 +01:00
if ( ! IsPlaying ( ) )
GetFrameAsync ( frame_n ) ;
2013-01-14 17:15:12 +01:00
no_amend = false ;
2007-01-21 07:30:19 +01:00
}
2011-01-16 08:16:40 +01:00
void VideoContext : : OnSubtitlesSave ( ) {
2013-01-14 17:15:12 +01:00
no_amend = true ;
2013-01-04 16:01:50 +01:00
context - > ass - > SetScriptInfo ( " VFR File " , config : : path - > MakeRelative ( GetTimecodesName ( ) , " ?script " ) . generic_string ( ) ) ;
context - > ass - > SetScriptInfo ( " Keyframes File " , config : : path - > MakeRelative ( GetKeyFramesName ( ) , " ?script " ) . generic_string ( ) ) ;
2012-07-24 04:40:34 +02:00
2011-01-16 08:16:40 +01:00
if ( ! IsLoaded ( ) ) {
2011-01-16 08:17:08 +01:00
context - > ass - > SetScriptInfo ( " Video File " , " " ) ;
2013-10-08 02:42:09 +02:00
context - > ass - > SaveUIState ( " Video Aspect Ratio " , " " ) ;
context - > ass - > SaveUIState ( " Video Position " , " " ) ;
2011-01-16 08:16:40 +01:00
return ;
}
2013-01-04 16:01:50 +01:00
std : : string ar ;
2013-01-20 22:05:24 +01:00
if ( ar_type = = AspectRatio : : Custom )
2013-01-04 16:01:50 +01:00
ar = " c " + std : : to_string ( ar_value ) ;
2011-01-16 08:16:40 +01:00
else
2013-01-20 22:05:24 +01:00
ar = std : : to_string ( ( int ) ar_type ) ;
2011-01-16 08:16:40 +01:00
2013-01-04 16:01:50 +01:00
context - > ass - > SetScriptInfo ( " Video File " , config : : path - > MakeRelative ( video_filename , " ?script " ) . generic_string ( ) ) ;
2014-01-12 00:45:05 +01:00
auto matrix = video_provider - > GetColorSpace ( ) ;
if ( ! matrix . empty ( ) )
context - > ass - > SetScriptInfo ( " YCbCr Matrix " , matrix ) ;
2013-10-08 02:42:09 +02:00
context - > ass - > SaveUIState ( " Video Aspect Ratio " , ar ) ;
context - > ass - > SaveUIState ( " Video Position " , std : : to_string ( frame_n ) ) ;
2011-01-16 08:16:40 +01:00
}
2007-01-21 07:30:19 +01:00
void VideoContext : : JumpToFrame ( int n ) {
2010-07-08 06:29:04 +02:00
if ( ! IsLoaded ( ) ) return ;
2007-01-21 07:30:19 +01:00
2011-12-05 06:26:58 +01:00
bool was_playing = IsPlaying ( ) ;
if ( was_playing )
Stop ( ) ;
2007-01-21 07:30:19 +01:00
2011-01-21 05:57:36 +01:00
frame_n = mid ( 0 , n , GetLength ( ) - 1 ) ;
2007-04-08 01:45:46 +02:00
2011-11-06 18:18:20 +01:00
GetFrameAsync ( frame_n ) ;
Seek ( frame_n ) ;
2011-12-05 06:26:58 +01:00
if ( was_playing )
Play ( ) ;
2007-01-21 07:30:19 +01:00
}
2010-07-08 06:29:04 +02:00
void VideoContext : : JumpToTime ( int ms , agi : : vfr : : Time end ) {
JumpToFrame ( FrameAtTime ( ms , end ) ) ;
2007-01-21 07:30:19 +01:00
}
2010-07-23 07:58:39 +02:00
void VideoContext : : GetFrameAsync ( int n ) {
2013-01-04 16:01:50 +01:00
provider - > RequestFrame ( n , TimeAtFrame ( n ) ) ;
2010-07-23 07:58:39 +02:00
}
2007-04-03 04:55:43 +02:00
2013-07-01 05:15:43 +02:00
std : : shared_ptr < VideoFrame > VideoContext : : GetFrame ( int n , bool raw ) {
2013-01-04 16:01:50 +01:00
return provider - > GetFrame ( n , TimeAtFrame ( n ) , raw ) ;
2007-04-03 04:55:43 +02:00
}
2013-01-04 16:01:50 +01:00
int VideoContext : : GetWidth ( ) const { return video_provider - > GetWidth ( ) ; }
int VideoContext : : GetHeight ( ) const { return video_provider - > GetHeight ( ) ; }
int VideoContext : : GetLength ( ) const { return video_provider - > GetFrameCount ( ) ; }
2011-12-05 06:26:45 +01:00
2011-01-16 08:15:53 +01:00
void VideoContext : : NextFrame ( ) {
2013-01-04 16:01:50 +01:00
if ( ! video_provider | | IsPlaying ( ) | | frame_n = = video_provider - > GetFrameCount ( ) )
2010-02-17 20:04:41 +01:00
return ;
JumpToFrame ( frame_n + 1 ) ;
2013-01-04 16:01:50 +01:00
if ( playAudioOnStep - > GetBool ( ) )
2012-02-02 00:58:58 +01:00
context - > audioController - > PlayRange ( TimeRange ( TimeAtFrame ( frame_n - 1 ) , TimeAtFrame ( frame_n ) ) ) ;
2010-02-17 20:04:41 +01:00
}
2011-01-16 08:15:53 +01:00
void VideoContext : : PrevFrame ( ) {
2013-01-04 16:01:50 +01:00
if ( ! video_provider | | IsPlaying ( ) | | frame_n = = 0 )
2010-02-17 20:04:41 +01:00
return ;
2011-01-16 08:15:53 +01:00
JumpToFrame ( frame_n - 1 ) ;
2013-01-04 16:01:50 +01:00
if ( playAudioOnStep - > GetBool ( ) )
2012-02-02 00:58:58 +01:00
context - > audioController - > PlayRange ( TimeRange ( TimeAtFrame ( frame_n ) , TimeAtFrame ( frame_n + 1 ) ) ) ;
2010-02-17 20:04:41 +01:00
}
2007-01-21 07:30:19 +01:00
void VideoContext : : Play ( ) {
2011-12-05 06:26:45 +01:00
if ( IsPlaying ( ) ) {
2007-01-21 07:30:19 +01:00
Stop ( ) ;
return ;
}
2011-10-29 06:30:52 +02:00
if ( ! IsLoaded ( ) ) return ;
2013-01-04 16:01:50 +01:00
start_ms = TimeAtFrame ( frame_n ) ;
end_frame = GetLength ( ) - 1 ;
2007-01-21 07:30:19 +01:00
2013-01-04 16:01:50 +01:00
context - > audioController - > PlayToEnd ( start_ms ) ;
2007-03-18 02:20:25 +01:00
2013-01-04 16:01:50 +01:00
playback_start_time = std : : chrono : : steady_clock : : now ( ) ;
2008-01-20 07:14:40 +01:00
playback . Start ( 10 ) ;
2007-01-21 07:30:19 +01:00
}
void VideoContext : : PlayLine ( ) {
2012-01-25 01:40:21 +01:00
Stop ( ) ;
2011-01-16 08:17:08 +01:00
AssDialogue * curline = context - > selectionController - > GetActiveLine ( ) ;
2007-01-21 07:30:19 +01:00
if ( ! curline ) return ;
2012-02-02 00:58:58 +01:00
context - > audioController - > PlayRange ( TimeRange ( curline - > Start , curline - > End ) ) ;
2007-01-21 07:30:19 +01:00
2011-12-05 06:26:45 +01:00
// Round-trip conversion to convert start to exact
2013-01-04 16:01:50 +01:00
int startFrame = FrameAtTime ( context - > selectionController - > GetActiveLine ( ) - > Start , agi : : vfr : : START ) ;
start_ms = TimeAtFrame ( startFrame ) ;
end_frame = FrameAtTime ( context - > selectionController - > GetActiveLine ( ) - > End , agi : : vfr : : END ) + 1 ;
2007-01-21 07:30:19 +01:00
JumpToFrame ( startFrame ) ;
2013-01-04 16:01:50 +01:00
playback_start_time = std : : chrono : : steady_clock : : now ( ) ;
2008-01-20 07:14:40 +01:00
playback . Start ( 10 ) ;
2007-01-21 07:30:19 +01:00
}
void VideoContext : : Stop ( ) {
2011-12-05 06:26:45 +01:00
if ( IsPlaying ( ) ) {
2007-01-21 07:30:19 +01:00
playback . Stop ( ) ;
2011-01-16 08:17:08 +01:00
context - > audioController - > Stop ( ) ;
2007-01-21 07:30:19 +01:00
}
}
2011-12-05 06:26:38 +01:00
void VideoContext : : OnPlayTimer ( wxTimerEvent & ) {
2013-01-04 16:01:50 +01:00
using namespace std : : chrono ;
int next_frame = FrameAtTime ( start_ms + duration_cast < milliseconds > ( steady_clock : : now ( ) - playback_start_time ) . count ( ) ) ;
if ( next_frame = = frame_n ) return ;
2011-12-05 06:26:45 +01:00
2013-01-04 16:01:50 +01:00
if ( next_frame > = end_frame )
2007-01-21 07:30:19 +01:00
Stop ( ) ;
2013-01-04 16:01:50 +01:00
else {
frame_n = next_frame ;
GetFrameAsync ( frame_n ) ;
Seek ( frame_n ) ;
2007-01-21 07:30:19 +01:00
}
}
2013-01-20 22:05:24 +01:00
double VideoContext : : GetARFromType ( AspectRatio type ) const {
switch ( type ) {
case AspectRatio : : Default : return ( double ) GetWidth ( ) / ( double ) GetHeight ( ) ;
case AspectRatio : : Fullscreen : return 4.0 / 3.0 ;
case AspectRatio : : Widescreen : return 16.0 / 9.0 ;
case AspectRatio : : Cinematic : return 2.35 ;
}
throw agi : : InternalError ( " Bad AR type " , nullptr ) ;
2007-01-21 07:30:19 +01:00
}
2013-01-20 22:05:24 +01:00
void VideoContext : : SetAspectRatio ( double value ) {
ar_type = AspectRatio : : Custom ;
ar_value = mid ( .5 , value , 5. ) ;
ARChange ( ar_type , ar_value ) ;
}
2007-01-21 07:30:19 +01:00
2013-01-20 22:05:24 +01:00
void VideoContext : : SetAspectRatio ( AspectRatio type ) {
ar_value = mid ( .5 , GetARFromType ( type ) , 5. ) ;
2013-01-04 16:01:50 +01:00
ar_type = type ;
ARChange ( ar_type , ar_value ) ;
2007-01-21 07:30:19 +01:00
}
2013-01-04 16:01:50 +01:00
void VideoContext : : LoadKeyframes ( agi : : fs : : path const & filename ) {
if ( filename = = keyframes_filename | | filename . empty ( ) ) return ;
2010-08-02 10:18:53 +02:00
try {
2013-01-04 16:01:50 +01:00
keyframes = agi : : keyframe : : Load ( filename ) ;
keyframes_filename = filename ;
KeyframesOpen ( keyframes ) ;
config : : mru - > Add ( " Keyframes " , filename ) ;
2010-08-02 10:18:53 +02:00
}
2010-12-31 22:02:17 +01:00
catch ( agi : : keyframe : : Error const & err ) {
2012-12-30 01:53:30 +01:00
wxMessageBox ( to_wx ( err . GetMessage ( ) ) , " Error opening keyframes file " , wxOK | wxICON_ERROR | wxCENTER , context - > parent ) ;
2013-01-04 16:01:50 +01:00
config : : mru - > Remove ( " Keyframes " , filename ) ;
2010-08-02 10:18:53 +02:00
}
2013-01-04 16:01:50 +01:00
catch ( agi : : fs : : FileSystemError const & err ) {
wxMessageBox ( to_wx ( err . GetMessage ( ) ) , " Error opening keyframes file " , wxOK | wxICON_ERROR | wxCENTER , context - > parent ) ;
config : : mru - > Remove ( " Keyframes " , filename ) ;
2010-08-02 10:18:53 +02:00
}
2007-01-21 07:30:19 +01:00
}
2013-01-04 16:01:50 +01:00
void VideoContext : : SaveKeyframes ( agi : : fs : : path const & filename ) {
agi : : keyframe : : Save ( filename , GetKeyFrames ( ) ) ;
config : : mru - > Add ( " Keyframes " , filename ) ;
2007-01-21 07:30:19 +01:00
}
2010-07-08 06:29:04 +02:00
void VideoContext : : CloseKeyframes ( ) {
2013-01-04 16:01:50 +01:00
keyframes_filename . clear ( ) ;
if ( video_provider )
keyframes = video_provider - > GetKeyFrames ( ) ;
2011-11-20 18:35:00 +01:00
else
2013-01-04 16:01:50 +01:00
keyframes . clear ( ) ;
KeyframesOpen ( keyframes ) ;
2007-01-21 07:30:19 +01:00
}
2013-01-04 16:01:50 +01:00
void VideoContext : : LoadTimecodes ( agi : : fs : : path const & filename ) {
if ( filename = = timecodes_filename | | filename . empty ( ) ) return ;
2010-07-08 06:29:04 +02:00
try {
2013-01-04 16:01:50 +01:00
ovr_fps = agi : : vfr : : Framerate ( filename ) ;
timecodes_filename = filename ;
config : : mru - > Add ( " Timecodes " , filename ) ;
2012-12-17 17:27:11 +01:00
OnSubtitlesCommit ( 0 , std : : set < const AssEntry * > ( ) ) ;
2013-01-04 16:01:50 +01:00
TimecodesOpen ( ovr_fps ) ;
2010-07-08 06:29:04 +02:00
}
2013-01-04 16:01:50 +01:00
catch ( agi : : fs : : FileSystemError const & err ) {
wxMessageBox ( to_wx ( err . GetMessage ( ) ) , " Error opening timecodes file " , wxOK | wxICON_ERROR | wxCENTER , context - > parent ) ;
config : : mru - > Remove ( " Timecodes " , filename ) ;
2010-07-08 06:29:04 +02:00
}
catch ( const agi : : vfr : : Error & e ) {
2013-01-04 16:01:50 +01:00
wxLogError ( " Timecode file parse error: %s " , to_wx ( e . GetMessage ( ) ) ) ;
config : : mru - > Remove ( " Timecodes " , filename ) ;
2010-07-08 06:29:04 +02:00
}
2007-01-21 07:30:19 +01:00
}
2013-01-04 16:01:50 +01:00
void VideoContext : : SaveTimecodes ( agi : : fs : : path const & filename ) {
2010-07-08 06:29:04 +02:00
try {
2013-01-04 16:01:50 +01:00
FPS ( ) . Save ( filename , IsLoaded ( ) ? GetLength ( ) : - 1 ) ;
config : : mru - > Add ( " Timecodes " , filename ) ;
2010-07-08 06:29:04 +02:00
}
2013-01-04 16:01:50 +01:00
catch ( agi : : fs : : FileSystemError const & err ) {
wxMessageBox ( to_wx ( err . GetMessage ( ) ) , " Error saving timecodes " , wxOK | wxICON_ERROR | wxCENTER , context - > parent ) ;
2010-07-08 06:29:04 +02:00
}
}
void VideoContext : : CloseTimecodes ( ) {
2013-01-04 16:01:50 +01:00
ovr_fps = agi : : vfr : : Framerate ( ) ;
timecodes_filename . clear ( ) ;
2013-12-12 00:11:06 +01:00
OnSubtitlesCommit ( 0 , std : : set < const AssEntry * > ( ) ) ;
2013-01-04 16:01:50 +01:00
TimecodesOpen ( video_fps ) ;
2007-01-23 07:32:16 +01:00
}
2010-07-08 06:29:04 +02:00
int VideoContext : : TimeAtFrame ( int frame , agi : : vfr : : Time type ) const {
2013-01-04 16:01:50 +01:00
return ( ovr_fps . IsLoaded ( ) ? ovr_fps : video_fps ) . TimeAtFrame ( frame , type ) ;
2010-07-08 06:29:04 +02:00
}
2013-01-04 16:01:50 +01:00
2010-07-08 06:29:04 +02:00
int VideoContext : : FrameAtTime ( int time , agi : : vfr : : Time type ) const {
2013-01-04 16:01:50 +01:00
return ( ovr_fps . IsLoaded ( ) ? ovr_fps : video_fps ) . FrameAtTime ( time , type ) ;
2007-01-23 07:32:16 +01:00
}
2010-07-23 07:58:39 +02:00
void VideoContext : : OnVideoError ( VideoProviderErrorEvent const & err ) {
wxLogError (
2011-09-28 21:43:11 +02:00
" Failed seeking video. The video file may be corrupt or incomplete. \n "
" Error message reported: %s " ,
2012-12-23 00:18:38 +01:00
to_wx ( err . GetMessage ( ) ) ) ;
2010-07-23 07:58:39 +02:00
}
void VideoContext : : OnSubtitlesError ( SubtitlesProviderErrorEvent const & err ) {
wxLogError (
2011-09-28 21:43:11 +02:00
" Failed rendering subtitles. Error message reported: %s " ,
2012-12-23 00:18:38 +01:00
to_wx ( err . GetMessage ( ) ) ) ;
2010-07-23 07:58:39 +02:00
}