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) {
AegiVideoFrame *frame;
static void delete_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);
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<wxMutexLocker> 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<AegiVideoFrame> ThreadedFrameSource::GetFrame(int frame, double time, bool 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
/// 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<AegiVideoFrame> 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<AegiVideoFrame> GetFrame(int frame, double time, bool raw = false);
std::tr1::shared_ptr<VideoProvider> 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<wxMutexLocker> 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<AegiVideoFrame> 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<wxMutexLocker> mutex)
: mutex(mutex), frame(frame), time(time) {
FrameReadyEvent(std::tr1::shared_ptr<AegiVideoFrame> frame, double time)
: frame(frame), time(time) {
}
};

View File

@ -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<AegiVideoFrame> 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) {

View File

@ -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<AegiVideoFrame> GetFrame(int n, bool raw = false);
void GetFrameAsync(int n);
/// @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 &) {
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();
}
}