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"
2012-12-01 20:36:30 +01:00
# include <cstring>
2009-09-10 15:06:40 +02:00
# include <wx/clipbrd.h>
# include <wx/config.h>
# include <wx/filename.h>
# include <wx/image.h>
2011-01-16 08:18:06 +01:00
# include <wx/msgdlg.h>
2009-09-10 15:06:40 +02:00
2011-01-16 08:17:08 +01:00
# include <libaegisub/keyframe.h>
2012-01-08 02:33:47 +01:00
# include <libaegisub/log.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"
2007-01-21 07:30:19 +01:00
# include "ass_style.h"
2009-09-10 15:06:40 +02:00
# 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"
2011-01-16 08:17:08 +01:00
# include "standard_paths.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"
# include "video_context.h"
2010-08-02 08:32:01 +02:00
# include "video_frame.h"
2007-01-21 07:30:19 +01:00
2010-05-19 02:44:37 +02:00
VideoContext : : VideoContext ( )
2011-12-05 06:26:45 +01:00
: playback ( this )
, startMS ( 0 )
, endFrame ( 0 )
2010-05-19 02:44:37 +02:00
, frame_n ( 0 )
, arValue ( 1. )
2010-05-20 10:55:58 +02:00
, arType ( 0 )
2010-05-19 02:44:37 +02:00
, hasSubtitles ( false )
2010-06-11 04:24:59 +02:00
, playAudioOnStep ( OPT_GET ( " Audio/Plays When Stepping Video " ) )
2013-01-14 17:15:12 +01:00
, no_amend ( false )
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 ( ) {
2011-09-28 21:43:11 +02:00
StandardPaths : : SetPathValue ( " ?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
2011-12-06 01:17:54 +01:00
videoFile . clear ( ) ;
2007-01-21 07:30:19 +01:00
// Remove provider
2010-07-08 06:29:04 +02:00
provider . reset ( ) ;
2011-12-06 01:17:36 +01:00
videoProvider = 0 ;
2011-12-22 22:29:38 +01:00
keyFrames . clear ( ) ;
keyFramesFilename . clear ( ) ;
videoFPS = agi : : vfr : : Framerate ( ) ;
KeyframesOpen ( keyFrames ) ;
if ( ! ovrFPS . IsLoaded ( ) ) TimecodesOpen ( videoFPS ) ;
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 ) ;
2011-08-27 08:42:03 +02:00
context - > ass - > AddFileSaveListener ( & VideoContext : : OnSubtitlesSave , this ) ;
2011-01-16 08:17:08 +01:00
}
2007-01-21 07:30:19 +01:00
void VideoContext : : SetVideo ( const wxString & filename ) {
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 {
2010-08-27 03:01:35 +02:00
provider . reset ( new ThreadedFrameSource ( filename , this ) ) ;
2010-07-23 08:40:12 +02:00
videoProvider = provider - > GetVideoProvider ( ) ;
2010-08-26 20:38:37 +02:00
videoFile = 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 ) {
context - > ass - > SetScriptInfo ( " PlayResX " , wxString : : Format ( " %d " , vx ) ) ;
context - > ass - > SetScriptInfo ( " PlayResY " , wxString : : Format ( " %d " , 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
context - > ass - > SetScriptInfo ( " PlayResX " , wxString : : Format ( " %d " , vx ) ) ;
context - > ass - > SetScriptInfo ( " PlayResY " , wxString : : Format ( " %d " , 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 ;
}
}
2010-07-23 07:58:39 +02:00
keyFrames = videoProvider - > GetKeyFrames ( ) ;
2010-07-08 06:29:04 +02:00
// Set frame rate
2010-07-23 07:58:39 +02:00
videoFPS = videoProvider - > GetFPS ( ) ;
2010-07-08 06:29:04 +02:00
if ( ovrFPS . IsLoaded ( ) ) {
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 ) {
ovrFPS = agi : : vfr : : Framerate ( ) ;
ovrTimecodeFile . 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
double dar = videoProvider - > GetDAR ( ) ;
if ( dar > 0 )
SetAspectRatio ( 4 , dar ) ;
2010-07-08 06:29:04 +02:00
// Set filename
2012-12-23 00:18:38 +01:00
config : : mru - > Add ( " Video " , from_wx ( filename ) ) ;
2011-12-06 01:17:54 +01:00
StandardPaths : : SetPathValue ( " ?video " , wxFileName ( filename ) . GetPath ( ) ) ;
2007-07-29 11:06:38 +02:00
2010-07-08 06:29:04 +02:00
// Show warning
2010-07-23 07:58:39 +02:00
wxString warning = videoProvider - > GetWarning ( ) ;
2012-04-03 19:38:38 +02:00
if ( ! warning . empty ( ) ) wxMessageBox ( warning , " Warning " , wxICON_WARNING | wxOK ) ;
2010-05-19 02:44:37 +02:00
2010-07-08 06:29:04 +02:00
hasSubtitles = false ;
2011-09-28 21:43:11 +02:00
if ( filename . Right ( 4 ) . Lower ( ) = = " .mkv " ) {
2010-07-08 06:29:04 +02:00
hasSubtitles = MatroskaWrapper : : HasSubtitles ( filename ) ;
2007-01-21 07:30:19 +01:00
}
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 ( ) ;
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 & ) { }
catch ( agi : : FileNotAccessibleError const & err ) {
2012-12-23 00:18:38 +01:00
config : : mru - > Remove ( " Video " , from_wx ( filename ) ) ;
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 ;
2012-01-08 02:35:31 +01:00
SetVideo ( videoFile . Clone ( ) ) ;
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 ;
2012-07-24 04:40:34 +02:00
context - > ass - > SetScriptInfo ( " VFR File " , MakeRelativePath ( GetTimecodesName ( ) , context - > ass - > filename ) ) ;
context - > ass - > SetScriptInfo ( " Keyframes File " , MakeRelativePath ( GetKeyFramesName ( ) , context - > ass - > filename ) ) ;
2011-01-16 08:16:40 +01:00
if ( ! IsLoaded ( ) ) {
2011-01-16 08:17:08 +01:00
context - > ass - > SetScriptInfo ( " Video File " , " " ) ;
context - > ass - > SetScriptInfo ( " Video Aspect Ratio " , " " ) ;
context - > ass - > SetScriptInfo ( " Video Position " , " " ) ;
2011-01-16 08:16:40 +01:00
return ;
}
wxString ar ;
if ( arType = = 4 )
ar = wxString : : Format ( " c%g " , arValue ) ;
else
ar = wxString : : Format ( " %d " , arType ) ;
2011-12-06 01:17:54 +01:00
context - > ass - > SetScriptInfo ( " Video File " , MakeRelativePath ( videoFile , context - > ass - > filename ) ) ;
2012-05-11 16:38:44 +02:00
context - > ass - > SetScriptInfo ( " YCbCr Matrix " , videoProvider - > GetColorSpace ( ) ) ;
2011-01-16 08:17:08 +01:00
context - > ass - > SetScriptInfo ( " Video Aspect Ratio " , ar ) ;
context - > ass - > SetScriptInfo ( " Video Position " , wxString : : Format ( " %d " , 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 ) {
2012-10-02 21:55:28 +02:00
provider - > RequestFrame ( n , TimeAtFrame ( n ) / 1000.0 ) ;
2010-07-23 07:58:39 +02:00
}
2007-04-03 04:55:43 +02:00
2012-09-25 01:35:27 +02:00
std : : shared_ptr < AegiVideoFrame > VideoContext : : GetFrame ( int n , bool raw ) {
2012-10-02 21:55:28 +02:00
return provider - > GetFrame ( n , TimeAtFrame ( n ) / 1000.0 , raw ) ;
2007-04-03 04:55:43 +02:00
}
2010-07-08 06:29:04 +02:00
int VideoContext : : GetWidth ( ) const {
2010-07-23 07:58:39 +02:00
return videoProvider - > GetWidth ( ) ;
2010-07-08 06:29:04 +02:00
}
int VideoContext : : GetHeight ( ) const {
2010-07-23 07:58:39 +02:00
return videoProvider - > GetHeight ( ) ;
2010-07-08 06:29:04 +02:00
}
2011-12-05 06:26:45 +01:00
int VideoContext : : GetLength ( ) const {
return videoProvider - > GetFrameCount ( ) ;
}
2011-01-16 08:15:53 +01:00
void VideoContext : : NextFrame ( ) {
2011-12-05 06:26:45 +01:00
if ( ! videoProvider | | IsPlaying ( ) | | frame_n = = videoProvider - > GetFrameCount ( ) )
2010-02-17 20:04:41 +01:00
return ;
JumpToFrame ( frame_n + 1 ) ;
// Start playing audio
2010-12-08 04:36:10 +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-12-08 04:36:10 +01:00
}
2010-02-17 20:04:41 +01:00
}
2011-01-16 08:15:53 +01:00
void VideoContext : : PrevFrame ( ) {
2011-12-05 06:26:45 +01:00
if ( ! videoProvider | | 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 ) ;
2010-02-17 20:04:41 +01:00
// Start playing audio
2010-12-08 04:36:10 +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-12-08 04:36:10 +01:00
}
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 ;
2007-01-21 07:30:19 +01:00
// Set variables
2011-12-05 06:26:45 +01:00
startMS = TimeAtFrame ( frame_n ) ;
endFrame = GetLength ( ) - 1 ;
2007-01-21 07:30:19 +01:00
// Start playing audio
2012-02-02 00:58:58 +01:00
context - > audioController - > PlayToEnd ( startMS ) ;
2007-03-18 02:20:25 +01:00
2007-01-21 07:30:19 +01:00
// Start timer
2008-01-20 07:14:40 +01:00
playTime . Start ( ) ;
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 ;
// Start playing audio
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
2011-12-22 22:28:51 +01:00
int startFrame = FrameAtTime ( context - > selectionController - > GetActiveLine ( ) - > Start , agi : : vfr : : START ) ;
2011-12-05 06:26:45 +01:00
startMS = TimeAtFrame ( startFrame ) ;
2011-12-22 22:28:51 +01:00
endFrame = FrameAtTime ( context - > selectionController - > GetActiveLine ( ) - > End , agi : : vfr : : END ) + 1 ;
2007-01-21 07:30:19 +01:00
// Jump to start
JumpToFrame ( startFrame ) ;
// Start timer
2011-12-05 06:26:45 +01:00
playTime . Start ( ) ;
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 & ) {
2011-12-05 06:26:45 +01:00
int nextFrame = FrameAtTime ( startMS + playTime . Time ( ) ) ;
// Same frame
if ( nextFrame = = frame_n ) return ;
2007-01-21 07:30:19 +01:00
// End
2011-12-05 06:26:45 +01:00
if ( nextFrame > = endFrame ) {
2007-01-21 07:30:19 +01:00
Stop ( ) ;
return ;
}
// Jump to next frame
frame_n = nextFrame ;
2011-12-05 06:26:58 +01:00
GetFrameAsync ( frame_n ) ;
Seek ( frame_n ) ;
2007-01-21 07:30:19 +01:00
}
2010-07-08 06:29:04 +02:00
double VideoContext : : GetARFromType ( int type ) const {
2011-01-16 08:17:08 +01:00
if ( type = = 0 ) return ( double ) GetWidth ( ) / ( double ) GetHeight ( ) ;
2010-07-08 06:29:04 +02:00
if ( type = = 1 ) return 4.0 / 3.0 ;
if ( type = = 2 ) return 16.0 / 9.0 ;
if ( type = = 3 ) return 2.35 ;
return 1.0 ; //error
2007-01-21 07:30:19 +01:00
}
2010-07-08 06:29:04 +02:00
void VideoContext : : SetAspectRatio ( int type , double value ) {
if ( type ! = 4 ) value = GetARFromType ( type ) ;
2007-01-21 07:30:19 +01:00
2010-07-08 06:29:04 +02:00
arType = type ;
2010-12-31 22:03:03 +01:00
arValue = mid ( .5 , value , 5. ) ;
2010-12-07 20:09:28 +01:00
ARChange ( arType , arValue ) ;
2007-01-21 07:30:19 +01:00
}
2010-07-08 06:29:04 +02:00
void VideoContext : : LoadKeyframes ( wxString filename ) {
if ( filename = = keyFramesFilename | | filename . empty ( ) ) return ;
2010-08-02 10:18:53 +02:00
try {
2012-12-23 00:18:38 +01:00
keyFrames = agi : : keyframe : : Load ( from_wx ( filename ) ) ;
2010-08-02 10:18:53 +02:00
keyFramesFilename = filename ;
2010-12-07 20:09:21 +01:00
KeyframesOpen ( keyFrames ) ;
2012-12-23 00:18:38 +01:00
config : : mru - > Add ( " Keyframes " , from_wx ( 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 ) ;
2012-12-23 00:18:38 +01:00
config : : mru - > Remove ( " Keyframes " , from_wx ( filename ) ) ;
2010-08-02 10:18:53 +02:00
}
2012-01-12 23:31:54 +01:00
catch ( agi : : FileSystemError const & ) {
2011-09-28 21:43:11 +02:00
wxLogError ( " Could not open file " + filename ) ;
2012-12-23 00:18:38 +01:00
config : : mru - > Remove ( " Keyframes " , from_wx ( filename ) ) ;
2010-08-02 10:18:53 +02:00
}
2007-01-21 07:30:19 +01:00
}
2010-07-08 06:29:04 +02:00
void VideoContext : : SaveKeyframes ( wxString filename ) {
2012-12-23 00:18:38 +01:00
agi : : keyframe : : Save ( from_wx ( filename ) , GetKeyFrames ( ) ) ;
config : : mru - > Add ( " Keyframes " , from_wx ( filename ) ) ;
2007-01-21 07:30:19 +01:00
}
2010-07-08 06:29:04 +02:00
void VideoContext : : CloseKeyframes ( ) {
keyFramesFilename . clear ( ) ;
2011-11-20 18:35:00 +01:00
if ( videoProvider )
2010-07-23 07:58:39 +02:00
keyFrames = videoProvider - > GetKeyFrames ( ) ;
2011-11-20 18:35:00 +01:00
else
2010-07-08 06:29:04 +02:00
keyFrames . clear ( ) ;
2010-12-07 20:09:21 +01:00
KeyframesOpen ( keyFrames ) ;
2007-01-21 07:30:19 +01:00
}
2010-07-08 06:29:04 +02:00
void VideoContext : : LoadTimecodes ( wxString filename ) {
if ( filename = = ovrTimecodeFile | | filename . empty ( ) ) return ;
try {
2012-12-23 00:18:38 +01:00
ovrFPS = agi : : vfr : : Framerate ( from_wx ( filename ) ) ;
2010-07-08 06:29:04 +02:00
ovrTimecodeFile = filename ;
2012-12-23 00:18:38 +01:00
config : : mru - > Add ( " Timecodes " , from_wx ( filename ) ) ;
2012-12-17 17:27:11 +01:00
OnSubtitlesCommit ( 0 , std : : set < const AssEntry * > ( ) ) ;
2010-12-31 22:03:18 +01:00
TimecodesOpen ( ovrFPS ) ;
2010-07-08 06:29:04 +02:00
}
2012-01-12 23:31:54 +01:00
catch ( const agi : : FileSystemError & ) {
2011-09-28 21:43:11 +02:00
wxLogError ( " Could not open file " + filename ) ;
2012-12-23 00:18:38 +01:00
config : : mru - > Remove ( " Timecodes " , from_wx ( filename ) ) ;
2010-07-08 06:29:04 +02:00
}
catch ( const agi : : vfr : : Error & e ) {
2011-09-28 21:43:48 +02:00
wxLogError ( " Timecode file parse error: %s " , e . GetMessage ( ) ) ;
2010-07-08 06:29:04 +02:00
}
2007-01-21 07:30:19 +01:00
}
2010-07-08 06:29:04 +02:00
void VideoContext : : SaveTimecodes ( wxString filename ) {
try {
2012-12-23 00:18:38 +01:00
FPS ( ) . Save ( from_wx ( filename ) , IsLoaded ( ) ? GetLength ( ) : - 1 ) ;
config : : mru - > Add ( " Timecodes " , from_wx ( filename ) ) ;
2010-07-08 06:29:04 +02:00
}
2012-01-12 23:31:54 +01:00
catch ( const agi : : FileSystemError & ) {
2011-09-28 21:43:11 +02:00
wxLogError ( " Could not write to " + filename ) ;
2010-07-08 06:29:04 +02:00
}
}
void VideoContext : : CloseTimecodes ( ) {
ovrFPS = agi : : vfr : : Framerate ( ) ;
ovrTimecodeFile . clear ( ) ;
2012-12-17 17:27:11 +01:00
OnSubtitlesCommit ( 0 , std : : set < const AssEntry * > ( ) ) ;
2010-12-31 22:03:18 +01:00
TimecodesOpen ( videoFPS ) ;
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 {
if ( ovrFPS . IsLoaded ( ) ) {
return ovrFPS . TimeAtFrame ( frame , type ) ;
}
return videoFPS . TimeAtFrame ( frame , type ) ;
}
int VideoContext : : FrameAtTime ( int time , agi : : vfr : : Time type ) const {
if ( ovrFPS . IsLoaded ( ) ) {
return ovrFPS . FrameAtTime ( time , type ) ;
}
return videoFPS . 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
}
2010-08-27 03:01:35 +02:00
void VideoContext : : OnExit ( ) {
// On unix wxThreadModule will shut down any still-running threads (and
// display a warning that it's doing so) before the destructor for
// VideoContext runs, so manually kill the thread
Get ( ) - > provider . reset ( ) ;
}