Pass around shared_ptrs to newly allocated AegiVideoFrames rather than pointers into a buffer of AegiVideoFrames in ThreadedFrameSource

Originally committed to SVN as r4789.
This commit is contained in:
Thomas Goyne 2010-09-15 22:10:48 +00:00
parent dca2bd43fe
commit 35b9769092
5 changed files with 21 additions and 41 deletions

View file

@ -58,12 +58,15 @@ struct invisible_line : public std::unary_function<const AssEntry*, bool> {
} }
}; };
AegiVideoFrame const& ThreadedFrameSource::ProcFrame(int frameNum, double time, bool raw) { static void delete_frame(AegiVideoFrame *frame) {
AegiVideoFrame *frame; frame->Clear();
delete frame;
}
std::tr1::shared_ptr<AegiVideoFrame> ThreadedFrameSource::ProcFrame(int frameNum, double time, bool raw) {
std::tr1::shared_ptr<AegiVideoFrame> frame(new AegiVideoFrame, delete_frame);
{ {
wxMutexLocker locker(providerMutex); wxMutexLocker locker(providerMutex);
frame = frameBuffer + frameBufferIdx;
frameBufferIdx = !frameBufferIdx;
try { try {
frame->CopyFrom(videoProvider->GetFrame(frameNum)); frame->CopyFrom(videoProvider->GetFrame(frameNum));
} }
@ -110,7 +113,7 @@ AegiVideoFrame const& ThreadedFrameSource::ProcFrame(int frameNum, double time,
provider->DrawSubtitles(*frame, time); provider->DrawSubtitles(*frame, time);
} }
return *frame; return frame;
} }
void *ThreadedFrameSource::Entry() { void *ThreadedFrameSource::Entry() {
@ -137,10 +140,7 @@ void *ThreadedFrameSource::Entry() {
} }
try { try {
AegiVideoFrame const& frame = ProcFrame(frameNum, time); FrameReadyEvent *evt = new FrameReadyEvent(ProcFrame(frameNum, time), time);
std::tr1::shared_ptr<wxMutexLocker> evtLock(new wxMutexLocker(evtMutex));
FrameReadyEvent *evt = new FrameReadyEvent(&frame, time, evtLock);
evt->SetEventType(EVT_FRAME_READY); evt->SetEventType(EVT_FRAME_READY);
parent->QueueEvent(evt); parent->QueueEvent(evt);
} }
@ -160,7 +160,6 @@ ThreadedFrameSource::ThreadedFrameSource(wxString videoFileName, wxEvtHandler *p
, parent(parent) , parent(parent)
, nextTime(-1.) , nextTime(-1.)
, jobReady(jobMutex) , jobReady(jobMutex)
, frameBufferIdx(0)
, run(true) , run(true)
{ {
Create(); Create();
@ -170,8 +169,6 @@ ThreadedFrameSource::~ThreadedFrameSource() {
run = false; run = false;
jobReady.Signal(); jobReady.Signal();
Wait(); Wait();
frameBuffer[0].Clear();
frameBuffer[1].Clear();
} }
void ThreadedFrameSource::LoadSubtitles(AssFile *subs) throw() { void ThreadedFrameSource::LoadSubtitles(AssFile *subs) throw() {
@ -192,7 +189,7 @@ void ThreadedFrameSource::RequestFrame(int frame, double time) throw() {
jobReady.Signal(); jobReady.Signal();
} }
AegiVideoFrame const& ThreadedFrameSource::GetFrame(int frame, double time, bool raw) { std::tr1::shared_ptr<AegiVideoFrame> ThreadedFrameSource::GetFrame(int frame, double time, bool raw) {
return ProcFrame(frame, time, raw); return ProcFrame(frame, time, raw);
} }

View file

@ -76,17 +76,10 @@ class ThreadedFrameSource : public wxThread {
wxCondition jobReady; ///< Signal for indicating that a frame has be requested 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 bool run; ///< Should the thread continue to run
void *Entry(); void *Entry();
AegiVideoFrame const& ProcFrame(int frameNum, double time, bool raw = false); std::tr1::shared_ptr<AegiVideoFrame> ProcFrame(int frameNum, double time, bool raw = false);
public: public:
/// @brief Load the passed subtitle file /// @brief Load the passed subtitle file
/// @param subs File to load /// @param subs File to load
@ -107,7 +100,7 @@ public:
/// @brief frame Frame number /// @brief frame Frame number
/// @brief time Exact start time of the frame in seconds /// @brief time Exact start time of the frame in seconds
/// @brief raw Get raw frame without subtitles /// @brief raw Get raw frame without subtitles
AegiVideoFrame const& GetFrame(int frame, double time, bool raw = false); std::tr1::shared_ptr<AegiVideoFrame> GetFrame(int frame, double time, bool raw = false);
std::tr1::shared_ptr<VideoProvider> GetVideoProvider() const { return videoProvider; } std::tr1::shared_ptr<VideoProvider> GetVideoProvider() const { return videoProvider; }
@ -121,24 +114,14 @@ public:
/// @class FrameReadyEvent /// @class FrameReadyEvent
/// @brief Event which signals that a requested frame is ready /// @brief Event which signals that a requested frame is ready
class FrameReadyEvent : public wxEvent { 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<wxMutexLocker> mutex;
public: public:
/// Frame which is ready; only guaranteed to be valid as long as this /// Frame which is ready
/// event object exists std::tr1::shared_ptr<AegiVideoFrame> frame;
const AegiVideoFrame *frame;
/// Time which was used for subtitle rendering /// Time which was used for subtitle rendering
double time; double time;
wxEvent *Clone() const { return new FrameReadyEvent(*this); }; wxEvent *Clone() const { return new FrameReadyEvent(*this); };
FrameReadyEvent(const AegiVideoFrame *frame, double time, std::tr1::shared_ptr<wxMutexLocker> mutex) FrameReadyEvent(std::tr1::shared_ptr<AegiVideoFrame> frame, double time)
: mutex(mutex), frame(frame), time(time) { : frame(frame), time(time) {
} }
}; };

View file

@ -295,7 +295,7 @@ void VideoContext::GetFrameAsync(int n) {
provider->RequestFrame(n,videoFPS.TimeAtFrame(n)/1000.0); provider->RequestFrame(n,videoFPS.TimeAtFrame(n)/1000.0);
} }
AegiVideoFrame const& VideoContext::GetFrame(int n, bool raw) { std::tr1::shared_ptr<AegiVideoFrame> VideoContext::GetFrame(int n, bool raw) {
return provider->GetFrame(n, videoFPS.TimeAtFrame(n)/1000.0, raw); return provider->GetFrame(n, videoFPS.TimeAtFrame(n)/1000.0, raw);
} }
@ -341,7 +341,7 @@ void VideoContext::SaveSnapshot(bool raw) {
if (!tryPath.FileExists()) break; 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) { void VideoContext::GetScriptSize(int &sw,int &sh) {

View file

@ -172,7 +172,7 @@ public:
/// @brief Get the video provider used for the currently open video /// @brief Get the video provider used for the currently open video
VideoProvider *GetProvider() const { return videoProvider.get(); } VideoProvider *GetProvider() const { return videoProvider.get(); }
AegiVideoFrame const& GetFrame(int n, bool raw = false); std::tr1::shared_ptr<AegiVideoFrame> GetFrame(int n, bool raw = false);
void GetFrameAsync(int n); void GetFrameAsync(int n);
/// @brief Save the currently displayed frame as an image /// @brief Save the currently displayed frame as an image

View file

@ -592,14 +592,14 @@ void VideoDisplay::FromScriptCoords(int *x, int *y) const {
void VideoDisplay::OnCopyToClipboard(wxCommandEvent &) { void VideoDisplay::OnCopyToClipboard(wxCommandEvent &) {
if (wxTheClipboard->Open()) { 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(); wxTheClipboard->Close();
} }
} }
void VideoDisplay::OnCopyToClipboardRaw(wxCommandEvent &) { void VideoDisplay::OnCopyToClipboardRaw(wxCommandEvent &) {
if (wxTheClipboard->Open()) { 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(); wxTheClipboard->Close();
} }
} }