static SubtitlesProvider *get_subs_provider(wxEvtHandler *parent) { try { return SubtitlesProviderFactory::GetProvider(); } catch (wxString const& err) { parent->AddPendingEvent(SubtitlesProviderErrorEvent(err)); return 0; } }
static std::unique_ptr<SubtitlesProvider> get_subs_provider(wxEvtHandler *evt_handler, agi::BackgroundRunner *br) { try { return SubtitlesProviderFactory::GetProvider(br); } catch (agi::Exception const& err) { evt_handler->AddPendingEvent(SubtitlesProviderErrorEvent(err.GetMessage())); return nullptr; } }
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); try { frame->CopyFrom(videoProvider->GetFrame(frameNum)); } catch (VideoProviderError const& err) { throw VideoProviderErrorEvent(err); } } // This deliberately results in a call to LoadSubtitles while a render // is pending making the queued render use the new file if (!raw) { try { wxMutexLocker locker(fileMutex); if (subs.get() && singleFrame != frameNum) { // Generally edits and seeks come in groups; if the last thing done // was seek it is more likely that the user will seek again and // vice versa. As such, if this is the first frame requested after // an edit, only export the currently visible lines (because the // other lines will probably not be viewed before the file changes // again), and if it's a different frame, export the entire file. if (singleFrame == -1) { AssExporter exporter(subs.get()); exporter.AddAutoFilters(); exporter.ExportTransform(); singleFrame = frameNum; // Copying a nontrivially sized AssFile is fairly slow, so // instead muck around with its innards to just temporarily // remove the non-visible lines without deleting them std::list<AssEntry*> visible; std::remove_copy_if(subs->Line.begin(), subs->Line.end(), std::back_inserter(visible), invisible_line(time)); try { std::swap(subs->Line, visible); provider->LoadSubtitles(subs.get()); std::swap(subs->Line, visible); } catch(...) { std::swap(subs->Line, visible); throw; } } else { provider->LoadSubtitles(subs.get()); subs.reset(); } } } catch (wxString const& err) { throw SubtitlesProviderErrorEvent(err); } provider->DrawSubtitles(*frame, time); } return frame; }
std::shared_ptr<VideoFrame> AsyncVideoProvider::ProcFrame(int frame_number, double time, bool raw) { // Find an unused buffer to use or allocate a new one if needed std::shared_ptr<VideoFrame> frame; for (auto& buffer : buffers) { if (buffer.use_count() == 1) { frame = buffer; break; } } if (!frame) { frame = std::make_shared<VideoFrame>(); buffers.push_back(frame); } try { source_provider->GetFrame(frame_number, *frame); } catch (VideoProviderError const& err) { throw VideoProviderErrorEvent(err); } if (raw || !subs_provider || !subs) return frame; try { if (single_frame != frame_number && single_frame != SUBS_FILE_ALREADY_LOADED) { // Generally edits and seeks come in groups; if the last thing done // was seek it is more likely that the user will seek again and // vice versa. As such, if this is the first frame requested after // an edit, only export the currently visible lines (because the // other lines will probably not be viewed before the file changes // again), and if it's a different frame, export the entire file. if (single_frame != NEW_SUBS_FILE) { subs_provider->LoadSubtitles(subs.get()); single_frame = SUBS_FILE_ALREADY_LOADED; } else { AssFixStylesFilter::ProcessSubs(subs.get()); single_frame = frame_number; subs_provider->LoadSubtitles(subs.get(), time); } } } catch (agi::Exception const& err) { throw SubtitlesProviderErrorEvent(err.GetMessage()); } try { subs_provider->DrawSubtitles(*frame, time / 1000.); } catch (agi::UserCancelException const&) { } return frame; }
std::shared_ptr<VideoFrame> ThreadedFrameSource::ProcFrame(int frame_number, double time, bool raw) { std::shared_ptr<VideoFrame> frame; try { frame = video_provider->GetFrame(frame_number); } catch (VideoProviderError const& err) { throw VideoProviderErrorEvent(err); } if (raw || !subs_provider || !subs) return frame; try { if (single_frame != frame_number && single_frame != SUBS_FILE_ALREADY_LOADED) { // Generally edits and seeks come in groups; if the last thing done // was seek it is more likely that the user will seek again and // vice versa. As such, if this is the first frame requested after // an edit, only export the currently visible lines (because the // other lines will probably not be viewed before the file changes // again), and if it's a different frame, export the entire file. if (single_frame != NEW_SUBS_FILE) { subs_provider->LoadSubtitles(subs.get()); single_frame = SUBS_FILE_ALREADY_LOADED; } else { AssFixStylesFilter().ProcessSubs(subs.get(), nullptr); single_frame = frame_number; subs_provider->LoadSubtitles(subs.get(), time); } } } catch (std::string const& err) { throw SubtitlesProviderErrorEvent(err); } try { subs_provider->DrawSubtitles(*frame, time / 1000.); } catch (agi::UserCancelException const&) { } return frame; }
std::shared_ptr<AegiVideoFrame> ThreadedFrameSource::ProcFrame(int frameNum, double time, bool raw) { std::shared_ptr<AegiVideoFrame> frame(new AegiVideoFrame, [](AegiVideoFrame *frame) { frame->Clear(); delete frame; }); { wxMutexLocker locker(providerMutex); try { frame->CopyFrom(videoProvider->GetFrame(frameNum)); } catch (VideoProviderError const& err) { throw VideoProviderErrorEvent(err); } } // This deliberately results in a call to LoadSubtitles while a render // is pending making the queued render use the new file if (!raw && provider) { try { wxMutexLocker locker(fileMutex); if (subs.get() && singleFrame != frameNum) { // Generally edits and seeks come in groups; if the last thing done // was seek it is more likely that the user will seek again and // vice versa. As such, if this is the first frame requested after // an edit, only export the currently visible lines (because the // other lines will probably not be viewed before the file changes // again), and if it's a different frame, export the entire file. if (singleFrame == -1) { // This will crash if any of the export filters try to use // anything but the subtitles, but that wouldn't be safe to // do anyway agi::Context c; memset(&c, 0, sizeof c); c.ass = subs.get(); AssExporter exporter(&c); exporter.AddAutoFilters(); exporter.ExportTransform(); singleFrame = frameNum; // Copying a nontrivially sized AssFile is fairly slow, so // instead muck around with its innards to just temporarily // remove the non-visible lines without deleting them std::deque<AssEntry*> full; for (auto& line : subs->Line) full.push_back(&line); subs->Line.remove_if(invisible_line(time)); try { provider->LoadSubtitles(subs.get()); subs->Line.clear(); boost::push_back(subs->Line, full | boost::adaptors::indirected); } catch(...) { subs->Line.clear(); boost::push_back(subs->Line, full | boost::adaptors::indirected); throw; } } else { provider->LoadSubtitles(subs.get()); subs.reset(); } } } catch (wxString const& err) { throw SubtitlesProviderErrorEvent(err); } provider->DrawSubtitles(*frame, time); } return frame; }