diff --git a/aegisub/src/threaded_frame_source.cpp b/aegisub/src/threaded_frame_source.cpp index e1bf1de61..a935b46be 100644 --- a/aegisub/src/threaded_frame_source.cpp +++ b/aegisub/src/threaded_frame_source.cpp @@ -58,12 +58,15 @@ struct invisible_line : public std::unary_function { } }; -AegiVideoFrame const& ThreadedFrameSource::ProcFrame(int frameNum, double time, bool raw) { - AegiVideoFrame *frame; +static void delete_frame(AegiVideoFrame *frame) { + frame->Clear(); + delete frame; +} + +std::tr1::shared_ptr ThreadedFrameSource::ProcFrame(int frameNum, double time, bool raw) { + std::tr1::shared_ptr frame(new AegiVideoFrame, delete_frame); { wxMutexLocker locker(providerMutex); - frame = frameBuffer + frameBufferIdx; - frameBufferIdx = !frameBufferIdx; try { frame->CopyFrom(videoProvider->GetFrame(frameNum)); } @@ -110,7 +113,7 @@ AegiVideoFrame const& ThreadedFrameSource::ProcFrame(int frameNum, double time, provider->DrawSubtitles(*frame, time); } - return *frame; + return frame; } void *ThreadedFrameSource::Entry() { @@ -137,10 +140,7 @@ void *ThreadedFrameSource::Entry() { } try { - AegiVideoFrame const& frame = ProcFrame(frameNum, time); - - std::tr1::shared_ptr evtLock(new wxMutexLocker(evtMutex)); - FrameReadyEvent *evt = new FrameReadyEvent(&frame, time, evtLock); + FrameReadyEvent *evt = new FrameReadyEvent(ProcFrame(frameNum, time), time); evt->SetEventType(EVT_FRAME_READY); parent->QueueEvent(evt); } @@ -160,7 +160,6 @@ ThreadedFrameSource::ThreadedFrameSource(wxString videoFileName, wxEvtHandler *p , parent(parent) , nextTime(-1.) , jobReady(jobMutex) -, frameBufferIdx(0) , run(true) { Create(); @@ -170,8 +169,6 @@ ThreadedFrameSource::~ThreadedFrameSource() { run = false; jobReady.Signal(); Wait(); - frameBuffer[0].Clear(); - frameBuffer[1].Clear(); } void ThreadedFrameSource::LoadSubtitles(AssFile *subs) throw() { @@ -192,7 +189,7 @@ void ThreadedFrameSource::RequestFrame(int frame, double time) throw() { jobReady.Signal(); } -AegiVideoFrame const& ThreadedFrameSource::GetFrame(int frame, double time, bool raw) { +std::tr1::shared_ptr ThreadedFrameSource::GetFrame(int frame, double time, bool raw) { return ProcFrame(frame, time, raw); } diff --git a/aegisub/src/threaded_frame_source.h b/aegisub/src/threaded_frame_source.h index 2697be01b..6545eadb8 100644 --- a/aegisub/src/threaded_frame_source.h +++ b/aegisub/src/threaded_frame_source.h @@ -76,17 +76,10 @@ class ThreadedFrameSource : public wxThread { wxCondition jobReady; ///< Signal for indicating that a frame has be requested - /// Frame buffers to render subtitles into - /// Two are needed so that a frame can be decoded/rendered while the GUI is - /// doing stuff with the other - AegiVideoFrame frameBuffer[2]; - /// Next frame buffer to use - int frameBufferIdx; - bool run; ///< Should the thread continue to run void *Entry(); - AegiVideoFrame const& ProcFrame(int frameNum, double time, bool raw = false); + std::tr1::shared_ptr ProcFrame(int frameNum, double time, bool raw = false); public: /// @brief Load the passed subtitle file /// @param subs File to load @@ -107,7 +100,7 @@ public: /// @brief frame Frame number /// @brief time Exact start time of the frame in seconds /// @brief raw Get raw frame without subtitles - AegiVideoFrame const& GetFrame(int frame, double time, bool raw = false); + std::tr1::shared_ptr GetFrame(int frame, double time, bool raw = false); std::tr1::shared_ptr GetVideoProvider() const { return videoProvider; } @@ -121,24 +114,14 @@ public: /// @class FrameReadyEvent /// @brief Event which signals that a requested frame is ready class FrameReadyEvent : public wxEvent { - /// Externally passed mutex that is kept locked as long as this or a copy - /// of this exists. Used to ensure that the next FrameReadyEvent is not - /// announced until this one is fully processed. - /// - /// Although tr1 does not require that shared_ptr be thread safe (due to - /// the standard having no concept of threads), all implementations have - /// at least a thread safe reference counter, which is all we happen to - /// need here. - std::tr1::shared_ptr mutex; public: - /// Frame which is ready; only guaranteed to be valid as long as this - /// event object exists - const AegiVideoFrame *frame; + /// Frame which is ready + std::tr1::shared_ptr frame; /// Time which was used for subtitle rendering double time; wxEvent *Clone() const { return new FrameReadyEvent(*this); }; - FrameReadyEvent(const AegiVideoFrame *frame, double time, std::tr1::shared_ptr mutex) - : mutex(mutex), frame(frame), time(time) { + FrameReadyEvent(std::tr1::shared_ptr frame, double time) + : frame(frame), time(time) { } }; diff --git a/aegisub/src/video_context.cpp b/aegisub/src/video_context.cpp index 29d67ff82..69b139e09 100644 --- a/aegisub/src/video_context.cpp +++ b/aegisub/src/video_context.cpp @@ -295,7 +295,7 @@ void VideoContext::GetFrameAsync(int n) { provider->RequestFrame(n,videoFPS.TimeAtFrame(n)/1000.0); } -AegiVideoFrame const& VideoContext::GetFrame(int n, bool raw) { +std::tr1::shared_ptr VideoContext::GetFrame(int n, bool raw) { return provider->GetFrame(n, videoFPS.TimeAtFrame(n)/1000.0, raw); } @@ -341,7 +341,7 @@ void VideoContext::SaveSnapshot(bool raw) { if (!tryPath.FileExists()) break; } - GetFrame(frame_n,raw).GetImage().SaveFile(path,wxBITMAP_TYPE_PNG); + GetFrame(frame_n,raw)->GetImage().SaveFile(path,wxBITMAP_TYPE_PNG); } void VideoContext::GetScriptSize(int &sw,int &sh) { diff --git a/aegisub/src/video_context.h b/aegisub/src/video_context.h index 55a04f4ec..f3318982e 100644 --- a/aegisub/src/video_context.h +++ b/aegisub/src/video_context.h @@ -172,7 +172,7 @@ public: /// @brief Get the video provider used for the currently open video VideoProvider *GetProvider() const { return videoProvider.get(); } - AegiVideoFrame const& GetFrame(int n, bool raw = false); + std::tr1::shared_ptr GetFrame(int n, bool raw = false); void GetFrameAsync(int n); /// @brief Save the currently displayed frame as an image diff --git a/aegisub/src/video_display.cpp b/aegisub/src/video_display.cpp index 38988a3b5..66f110152 100644 --- a/aegisub/src/video_display.cpp +++ b/aegisub/src/video_display.cpp @@ -592,14 +592,14 @@ void VideoDisplay::FromScriptCoords(int *x, int *y) const { void VideoDisplay::OnCopyToClipboard(wxCommandEvent &) { if (wxTheClipboard->Open()) { - wxTheClipboard->SetData(new wxBitmapDataObject(wxBitmap(VideoContext::Get()->GetFrame(currentFrame).GetImage(),24))); + wxTheClipboard->SetData(new wxBitmapDataObject(wxBitmap(VideoContext::Get()->GetFrame(currentFrame)->GetImage(),24))); wxTheClipboard->Close(); } } void VideoDisplay::OnCopyToClipboardRaw(wxCommandEvent &) { if (wxTheClipboard->Open()) { - wxTheClipboard->SetData(new wxBitmapDataObject(wxBitmap(VideoContext::Get()->GetFrame(currentFrame,true).GetImage(),24))); + wxTheClipboard->SetData(new wxBitmapDataObject(wxBitmap(VideoContext::Get()->GetFrame(currentFrame,true)->GetImage(),24))); wxTheClipboard->Close(); } }