mirror of https://github.com/odrling/Aegisub
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:
parent
dca2bd43fe
commit
35b9769092
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue