diff --git a/core/ass_dialogue.cpp b/core/ass_dialogue.cpp index b8875ca5e..95de06cb0 100644 --- a/core/ass_dialogue.cpp +++ b/core/ass_dialogue.cpp @@ -47,6 +47,8 @@ ////////////////////// AssDialogue ////////////////////// // Constructs AssDialogue AssDialogue::AssDialogue() { + Tracker = 0; + Type = ENTRY_DIALOGUE; group = _T("[Events]"); @@ -67,6 +69,8 @@ AssDialogue::AssDialogue() { AssDialogue::AssDialogue(wxString _data,bool IsSSA) { + Tracker = 0; + Type = ENTRY_DIALOGUE; group = _T("[Events]"); data = _data; diff --git a/core/ass_dialogue.h b/core/ass_dialogue.h index 637b51b6e..ff60c6415 100644 --- a/core/ass_dialogue.h +++ b/core/ass_dialogue.h @@ -42,6 +42,7 @@ #include #include "ass_entry.h" #include "ass_time.h" +class FexTracker; ////////////// @@ -165,6 +166,7 @@ public: wxString Actor; // Actor name wxString Effect; // Effect name wxString Text; // Raw text data + FexTracker *Tracker; // Point tracker bool Parse(bool IsSSA=false); // Parses raw ASS data into everything else void ParseASSTags(); // Parses text to generate block information (doesn't update data) diff --git a/core/bitmaps/button_track_points.bmp b/core/bitmaps/button_track_points.bmp new file mode 100644 index 000000000..a751c8d22 Binary files /dev/null and b/core/bitmaps/button_track_points.bmp differ diff --git a/core/bitmaps/button_track_split.bmp b/core/bitmaps/button_track_split.bmp new file mode 100644 index 000000000..06a5f1d82 Binary files /dev/null and b/core/bitmaps/button_track_split.bmp differ diff --git a/core/frame_main.h b/core/frame_main.h index 729d0f63b..d79e2bfd9 100644 --- a/core/frame_main.h +++ b/core/frame_main.h @@ -105,6 +105,7 @@ private: void OnVideoPlayLine(wxCommandEvent &event); void OnVideoStop(wxCommandEvent &event); void OnVideoToggleScroll(wxCommandEvent &event); + void OnVideoTrackPoints(wxCommandEvent &event); void OnKeyDown(wxKeyEvent &event); @@ -321,6 +322,7 @@ enum { Video_Play_Line, Video_Stop, Video_Auto_Scroll, + Video_Track_Points, Menu_File_Recent = 2000, Menu_Video_Recent = 2200, diff --git a/core/frame_main_events.cpp b/core/frame_main_events.cpp index 89f6372f1..90a0e8937 100644 --- a/core/frame_main_events.cpp +++ b/core/frame_main_events.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include "subs_grid.h" #include "frame_main.h" #include "video_display.h" @@ -71,6 +72,8 @@ #include "toggle_bitmap.h" #include "dialog_hotkeys.h" #include "dialog_timing_processor.h" +#include "FexTracker.h" +#include "FexTrackingFeature.h" //////////////////// @@ -83,6 +86,7 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame) EVT_BUTTON(Video_Play_Line, FrameMain::OnVideoPlayLine) EVT_BUTTON(Video_Stop, FrameMain::OnVideoStop) EVT_TOGGLEBUTTON(Video_Auto_Scroll, FrameMain::OnVideoToggleScroll) + EVT_BUTTON(Video_Track_Points, FrameMain::OnVideoTrackPoints) EVT_CLOSE(FrameMain::OnCloseWindow) @@ -1123,6 +1127,47 @@ void FrameMain::OnVideoToggleScroll(wxCommandEvent &event) { } +/////////////////// +// Track current line +void FrameMain::OnVideoTrackPoints(wxCommandEvent &event) { + videoBox->videoDisplay->Stop(); + + // Get line + AssDialogue *curline = SubsBox->GetDialogue(EditBox->linen); + if (!curline) return; + + // Get Video + bool usedDirectshow; + VideoProvider *movie = new VideoProvider(videoBox->videoDisplay->videoName, wxString(_T("")), 1.0,usedDirectshow,true); + + // Create Tracker + if( curline->Tracker ) delete curline->Tracker; + curline->Tracker = new FexTracker( movie->GetWidth(), movie->GetHeight(), 250 ); + curline->Tracker->minFeatures = 250; + + // Allocate temp image + float* FloatImg = new float[ movie->GetWidth()*movie->GetHeight() ]; + + int StartFrame = VFR_Output.CorrectFrameAtTime(curline->Start.GetMS(),true); + int EndFrame = VFR_Output.CorrectFrameAtTime(curline->End.GetMS(),false); + + for( int Frame = StartFrame; Frame <= EndFrame; Frame ++ ) + { + wxString Text; + Text = wxString::Format( _T("Tracking ... %.2f %%"), float(Frame-StartFrame)/(EndFrame-StartFrame)*100.0f ); + videoBox->videoDisplay->DrawText( wxPoint(20,20), Text ); + + movie->GetFloatFrame( FloatImg, Frame ); + curline->Tracker->ProcessImage( FloatImg ); + } + + delete FloatImg; + delete movie; + + videoBox->videoDisplay->RefreshVideo(); +} + + /////////////////////////////// // Choose a different language void FrameMain::OnChooseLanguage (wxCommandEvent &event) { diff --git a/core/res.rc b/core/res.rc index ce60608f7..9817a1287 100644 --- a/core/res.rc +++ b/core/res.rc @@ -79,6 +79,8 @@ shift_to_frame_disable BITMAP "bitmaps/shift_to_frame_disable.bmp" button_play BITMAP "bitmaps/button_play.bmp" button_stop BITMAP "bitmaps/button_stop.bmp" +button_track_points BITMAP "bitmaps/button_track_points.bmp" + button_bold BITMAP "bitmaps/button_bold.bmp" button_italics BITMAP "bitmaps/button_italics.bmp" button_underline BITMAP "bitmaps/button_underline.bmp" diff --git a/core/video_box.cpp b/core/video_box.cpp index 24b36ce00..3fab70338 100644 --- a/core/video_box.cpp +++ b/core/video_box.cpp @@ -59,6 +59,8 @@ VideoBox::VideoBox(wxPanel *parent) { AutoScroll = new ToggleBitmap(videoPage,Video_Auto_Scroll,wxBITMAP(toggle_video_autoscroll),wxSize(30,-1)); AutoScroll->SetToolTip(_("Toggle autoscroll of video")); AutoScroll->SetValue(Options.AsBool(_T("Sync video with subs"))); + wxBitmapButton *VideoTrackPointsButton = new wxBitmapButton(videoPage,Video_Track_Points,wxBITMAP(button_track_points),wxDefaultPosition,wxSize(25,-1)); + VideoTrackPointsButton->SetToolTip(_("Track point movements in video")); // Seek videoSlider = new VideoSlider(videoPage,-1); @@ -93,6 +95,7 @@ VideoBox::VideoBox(wxPanel *parent) { videoBottomSizer->Add(AutoScroll,0,wxTOP|wxBOTTOM|wxALIGN_CENTER|wxEXPAND,2); videoBottomSizer->Add(VideoPosition,1,wxLEFT|wxALIGN_CENTER,5); videoBottomSizer->Add(VideoSubsPos,1,wxALIGN_CENTER,0); + videoBottomSizer->Add(VideoTrackPointsButton,0,wxTOP|wxBOTTOM|wxALIGN_CENTER,2); VideoSizer = new wxBoxSizer(wxVERTICAL); VideoSizer->Add(videoDisplay,0,wxEXPAND,0); VideoSizer->Add(videoSliderSizer,0,wxEXPAND,0); diff --git a/core/video_display.cpp b/core/video_display.cpp index 0f8fa1ed0..e3c1b3cc7 100644 --- a/core/video_display.cpp +++ b/core/video_display.cpp @@ -53,6 +53,8 @@ #include #include #include +#include "FexTracker.h" +#include "FexTrackingFeature.h" /////// @@ -275,6 +277,8 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) { // Draw frame dc.DrawBitmap(GetFrame(frame_n),0,0); + // Draw the control points for FexTracker + DrawTrackingOverlay( dc ); // Current position info if (x >= 0 && x < w && y >= 0 && y < h) { @@ -523,6 +527,44 @@ void VideoDisplay::OnCopyCoords(wxCommandEvent &event) { } +////////////////// +// Draw Tracking Overlay +void VideoDisplay::DrawTrackingOverlay( wxDC &dc ) +{ + if( IsPlaying ) return; + + // Get line + AssDialogue *curline = grid->GetDialogue(grid->editBox->linen); + if( !curline || !curline->Tracker ) return; + + int StartFrame = VFR_Output.CorrectFrameAtTime(curline->Start.GetMS(),true); + int EndFrame = VFR_Output.CorrectFrameAtTime(curline->End.GetMS(),false); + + if( frame_nEndFrame ) return; + + int localframe = frame_n - StartFrame; + if( curline->Tracker->GetFrame() <= localframe ) return; + + dc.SetPen(wxPen(wxColour(255,255,255),1)); + dc.SetLogicalFunction(wxINVERT); + + for( int i=0;iTracker->GetCount();i++ ) + { + FexTrackingFeature* f = (*curline->Tracker)[i]; + if( f->StartTime > localframe ) continue; + int llf = localframe - f->StartTime; + if( f->Pos.size() <= llf ) continue; + vec2 pt = f->Pos[llf]; + pt.x *= provider->GetZoom(); + pt.y *= provider->GetZoom(); + pt.x = int(pt.x); + pt.y = int(pt.y); + dc.DrawLine( pt.x-2, pt.y, pt.x+3, pt.y ); + dc.DrawLine( pt.x, pt.y-2, pt.x, pt.y+3 ); + } +} + + ////////////////// // Refresh screen void VideoDisplay::RefreshVideo() { @@ -530,6 +572,29 @@ void VideoDisplay::RefreshVideo() { wxClientDC dc(this); dc.BeginDrawing(); dc.DrawBitmap(GetFrame(),0,0); + + // Draw the control points for FexTracker + DrawTrackingOverlay( dc ); + + dc.EndDrawing(); +} + + +////////////////// +// DrawVideoWithOverlay +void VideoDisplay::DrawText( wxPoint Pos, wxString text ) { + // Draw frame + wxClientDC dc(this); + dc.BeginDrawing(); + dc.SetBrush(wxBrush(wxColour(128,128,128),wxSOLID)); + dc.DrawRectangle( 0,0, provider->GetWidth(), provider->GetHeight() ); + dc.SetTextForeground(wxColour(64,64,64)); + dc.DrawText(text,Pos.x+1,Pos.y-1); + dc.DrawText(text,Pos.x+1,Pos.y+1); + dc.DrawText(text,Pos.x-1,Pos.y-1); + dc.DrawText(text,Pos.x-1,Pos.y+1); + dc.SetTextForeground(wxColour(255,255,255)); + dc.DrawText(text,Pos.x,Pos.y); dc.EndDrawing(); } diff --git a/core/video_display.h b/core/video_display.h index a6b7bbde8..51d645077 100644 --- a/core/video_display.h +++ b/core/video_display.h @@ -89,6 +89,8 @@ private: void OnCopyCoords(wxCommandEvent &event); void OnPlayTimer(wxTimerEvent &event); + void DrawTrackingOverlay( wxDC &dc ); + public: VideoProvider *provider; @@ -119,6 +121,7 @@ public: void JumpToTime(int ms); void RefreshSubtitles(); void RefreshVideo(); + void DrawText( wxPoint Pos, wxString Text ); void UpdatePositionDisplay(); void SetAspectRatio(int type); void SetZoom(double value); diff --git a/core/video_provider.cpp b/core/video_provider.cpp index 69c5a5c46..f30b56bd7 100644 --- a/core/video_provider.cpp +++ b/core/video_provider.cpp @@ -57,15 +57,22 @@ VideoProvider::VideoProvider(wxString _filename, wxString _subfilename, double _ dar = GetSourceWidth()/(double)GetSourceHeight(); - SubtitledVideo = ApplySubtitles(subfilename, RGB32Video); + if( _subfilename == _T("") ) SubtitledVideo = RGB32Video; + else SubtitledVideo = ApplySubtitles(subfilename, RGB32Video); +/* + if( _zoom == 1.0 ) ResizedVideo = SubtitledVideo; + else ResizedVideo = ApplyDARZoom(zoom, dar, SubtitledVideo); +*/ ResizedVideo = ApplyDARZoom(zoom, dar, SubtitledVideo); + + vi = ResizedVideo->GetVideoInfo(); } VideoProvider::~VideoProvider() { RGB32Video = NULL; SubtitledVideo = NULL; ResizedVideo = NULL; - delete data; + if( data ) delete data; } void VideoProvider::RefreshSubtitles() { @@ -228,6 +235,25 @@ wxBitmap VideoProvider::GetFrame(int n, bool force) { return wxBitmap(last_frame); } +void VideoProvider::GetFloatFrame(float* Buffer, int n) { + wxMutexLocker lock(AviSynthMutex); + + PVideoFrame frame = ResizedVideo->GetFrame(n,env); + + int rs = vi.RowSize(); + const unsigned char* src = frame->GetReadPtr(); + int srcpitch = frame->GetPitch(); + + for( int i = 0; i < vi.height; i++ ) + { + for( int x=0; xGetVideoInfo().width; }; int GetSourceHeight() { return RGB32Video->GetVideoInfo().height; };