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) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue