From 5b42203fc65ae2a83d840c0847f3c28907763c5f Mon Sep 17 00:00:00 2001 From: Vasily Date: Fri, 25 Mar 2022 22:05:08 +0100 Subject: [PATCH] Add dropAllAnimations feature Original implementation by JustAMan, mostly in the following three commits sans unrelated changes. Backported by Oneric. https://github.com/jellyfin/JavascriptSubtitlesOctopus/commit/d3bc4724a0ce07f7cd02194834222999d7160a18 https://github.com/jellyfin/JavascriptSubtitlesOctopus/commit/a66e79768b00b50d5a7e9651d2410677d346d688 https://github.com/jellyfin/JavascriptSubtitlesOctopus/commit/971a9979517738ec1847350cb057d61c8840d605 The commits have also been adjusted to apply on top of current upstream master, to use the animations detection from the previous commit instead of the faulty original logic and the scanned_events variable was added. Also added documentation which was missing in the original commits. Co-authored-by: Oneric --- README.md | 6 ++++++ src/SubtitleOctopus.cpp | 25 +++++++++++++++++++++++++ src/SubtitleOctopus.idl | 1 + src/post-worker.js | 2 ++ src/pre-worker.js | 1 + src/subtitles-octopus.js | 4 +++- 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c45ffd7..005a0246 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,12 @@ When creating an instance of SubtitleOctopus, you can set the following options: - `maxRenderHeight`: The maximum rendering height of the subtitles canvas. Beyond this subtitles will be upscaled by the browser. (Default: `0` - no limit) +- `dropAllAnimations`: If set to true, attempt to discard all animated tags. + Enabling this may severly mangle complex subtitles and + should only be considered as an last ditch effort of uncertain success + for hardware otherwise incapable of displaing anything. + Will not reliably work with manually edited or allocated events. + (Default: `false` - do nothing) ### Rendering Modes #### JS Blending diff --git a/src/SubtitleOctopus.cpp b/src/SubtitleOctopus.cpp index 57ea3310..06616f9c 100644 --- a/src/SubtitleOctopus.cpp +++ b/src/SubtitleOctopus.cpp @@ -235,6 +235,8 @@ class SubtitleOctopus { private: ReusableBuffer2D m_blend; RenderBlendResult m_blendResult; + bool drop_animations; + int scanned_events; // next unscanned event index public: ASS_Library* ass_library; ASS_Renderer* ass_renderer; @@ -252,12 +254,33 @@ class SubtitleOctopus { track = NULL; canvas_w = 0; canvas_h = 0; + drop_animations = false; + scanned_events = 0; } void setLogLevel(int level) { log_level = level; } + void setDropAnimations(int value) { + drop_animations = !!value; + if (drop_animations) + scanAnimations(scanned_events); + } + + /* + * \brief Scan events starting at index i for animations + * and discard animated tags when found. + * Note that once animated tags were dropped they cannot be restored. + * Updates the class member scanned_events to last scanned index. + */ + void scanAnimations(int i) { + for (; i < track->n_events; i++) { + _is_event_animated(track->events + i, drop_animations); + } + scanned_events = i; + } + void initLibrary(int frame_w, int frame_h) { ass_library = ass_library_init(); if (!ass_library) { @@ -287,6 +310,7 @@ class SubtitleOctopus { fprintf(stderr, "jso: Failed to start a track\n"); exit(4); } + scanAnimations(0); } void createTrackMem(char *buf, unsigned long bufsize) { @@ -296,6 +320,7 @@ class SubtitleOctopus { fprintf(stderr, "jso: Failed to start a track\n"); exit(4); } + scanAnimations(0); } void removeTrack() { diff --git a/src/SubtitleOctopus.idl b/src/SubtitleOctopus.idl index 5b7f033b..578a32db 100644 --- a/src/SubtitleOctopus.idl +++ b/src/SubtitleOctopus.idl @@ -171,6 +171,7 @@ interface SubtitleOctopus { attribute ASS_Renderer ass_renderer; attribute ASS_Library ass_library; void setLogLevel(long level); + void setDropAnimations(long value); void initLibrary(long frame_w, long frame_h); void createTrack(DOMString subfile); void createTrackMem(DOMString buf, unsigned long bufsize); diff --git a/src/post-worker.js b/src/post-worker.js index 6c01f39a..e4b4e653 100644 --- a/src/post-worker.js +++ b/src/post-worker.js @@ -8,6 +8,7 @@ self.nextIsRaf = false; self.lastCurrentTimeReceivedAt = Date.now(); self.targetFps = 24; self.libassMemoryLimit = 0; // in MiB +self.dropAllAnimations = false; self.width = 0; self.height = 0; @@ -565,6 +566,7 @@ function onMessageFromMainEmscriptenThread(message) { self.targetFps = message.data.targetFps || self.targetFps; self.libassMemoryLimit = message.data.libassMemoryLimit || self.libassMemoryLimit; self.libassGlyphLimit = message.data.libassGlyphLimit || 0; + self.dropAllAnimations = !!message.data.dropAllAnimations || self.dropAllAnimations; removeRunDependency('worker-init'); postMessage({ target: "ready", diff --git a/src/pre-worker.js b/src/pre-worker.js index 09f86b76..cba574dc 100644 --- a/src/pre-worker.js +++ b/src/pre-worker.js @@ -108,6 +108,7 @@ Module['onRuntimeInitialized'] = function () { self.blendH = Module._malloc(4); self.octObj.initLibrary(screen.width, screen.height); + self.octObj.setDropAnimations(self.dropAllAnimations); self.octObj.createTrack("/sub.ass"); self.ass_track = self.octObj.track; self.ass_library = self.octObj.ass_library; diff --git a/src/subtitles-octopus.js b/src/subtitles-octopus.js index a1d9ca4c..77a349b6 100644 --- a/src/subtitles-octopus.js +++ b/src/subtitles-octopus.js @@ -20,6 +20,7 @@ var SubtitlesOctopus = function (options) { self.prescaleFactor = options.prescaleFactor || 1.0; self.prescaleHeightLimit = options.prescaleHeightLimit || 1080; self.maxRenderHeight = options.maxRenderHeight || 0; // 0 - no limit + self.dropAllAnimations = options.dropAllAnimations || false; // attempt to remove all animations as a last ditch effort for displaying on weak hardware; may severly mangle subtitles if enabled self.isOurCanvas = false; // (internal) we created canvas and manage it self.video = options.video; // HTML video element (optional if canvas specified) self.canvasParent = null; // (internal) HTML canvas parent element @@ -113,7 +114,8 @@ var SubtitlesOctopus = function (options) { debug: self.debug, targetFps: self.targetFps, libassMemoryLimit: self.libassMemoryLimit, - libassGlyphLimit: self.libassGlyphLimit + libassGlyphLimit: self.libassGlyphLimit, + dropAllAnimations: self.dropAllAnimations }); };