summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/basilisk/components/nsBrowserGlue.js36
-rw-r--r--application/basilisk/confvars.sh2
-rw-r--r--application/palemoon/components/downloads/content/downloads.js6
-rw-r--r--application/palemoon/components/nsBrowserGlue.js96
-rw-r--r--application/palemoon/themes/linux/browser.css12
-rw-r--r--application/palemoon/themes/osx/browser.css12
-rw-r--r--application/palemoon/themes/windows/browser.css12
-rw-r--r--dom/base/nsNodeUtils.cpp10
-rw-r--r--dom/webidl/IntersectionObserver.webidl4
-rw-r--r--image/IDecodingTask.cpp15
-rw-r--r--image/IDecodingTask.h8
-rw-r--r--image/ImageOps.cpp2
-rw-r--r--image/SourceBuffer.cpp14
-rw-r--r--image/SourceBuffer.h7
-rw-r--r--image/decoders/nsWebPDecoder.cpp4
-rw-r--r--js/src/jsapi.h2
-rw-r--r--js/src/vm/Stopwatch.cpp25
-rw-r--r--media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp13
-rw-r--r--media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp46
-rw-r--r--media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h4
-rw-r--r--media/libwebp/AUTHORS5
-rw-r--r--media/libwebp/NEWS20
-rw-r--r--media/libwebp/README9
-rw-r--r--media/libwebp/README.mux31
-rw-r--r--media/libwebp/UXPCHANGES1
-rw-r--r--media/libwebp/dec/alphai_dec.h2
-rw-r--r--media/libwebp/dec/common_dec.h2
-rw-r--r--media/libwebp/dec/frame_dec.c9
-rw-r--r--media/libwebp/dec/idec_dec.c19
-rw-r--r--media/libwebp/dec/vp8_dec.h2
-rw-r--r--media/libwebp/dec/vp8i_dec.h4
-rw-r--r--media/libwebp/dec/vp8l_dec.c205
-rw-r--r--media/libwebp/dec/vp8li_dec.h2
-rw-r--r--media/libwebp/dec/webpi_dec.h2
-rw-r--r--media/libwebp/demux/demux.c2
-rw-r--r--media/libwebp/dsp/dsp.h6
-rw-r--r--media/libwebp/dsp/lossless.c2
-rw-r--r--media/libwebp/dsp/lossless.h14
-rw-r--r--media/libwebp/dsp/msa_macro.h2
-rw-r--r--media/libwebp/dsp/quant.h70
-rw-r--r--media/libwebp/dsp/rescaler.c4
-rw-r--r--media/libwebp/dsp/rescaler_neon.c18
-rw-r--r--media/libwebp/dsp/rescaler_sse2.c35
-rw-r--r--media/libwebp/dsp/yuv.h2
-rw-r--r--media/libwebp/enc/cost_enc.h2
-rw-r--r--media/libwebp/enc/histogram_enc.h10
-rw-r--r--media/libwebp/enc/vp8i_enc.h6
-rw-r--r--media/libwebp/enc/vp8li_enc.h2
-rw-r--r--media/libwebp/utils/bit_reader_inl_utils.h2
-rw-r--r--media/libwebp/utils/bit_reader_utils.h2
-rw-r--r--media/libwebp/utils/bit_writer_utils.h2
-rw-r--r--media/libwebp/utils/filters_utils.h2
-rw-r--r--media/libwebp/utils/quant_levels_dec_utils.c8
-rw-r--r--media/libwebp/utils/quant_levels_dec_utils.h2
-rw-r--r--media/libwebp/utils/quant_levels_utils.h2
-rw-r--r--media/libwebp/utils/random_utils.h2
-rw-r--r--media/libwebp/utils/rescaler_utils.h2
-rw-r--r--media/libwebp/utils/thread_utils.h2
-rw-r--r--media/libwebp/utils/utils.h28
-rw-r--r--media/libwebp/webp/decode.h14
-rw-r--r--media/libwebp/webp/demux.h2
-rw-r--r--media/libwebp/webp/encode.h2
-rw-r--r--media/libwebp/webp/format_constants.h2
-rw-r--r--media/libwebp/webp/mux.h2
-rw-r--r--media/libwebp/webp/mux_types.h2
-rw-r--r--media/libwebp/webp/types.h2
-rw-r--r--modules/libpref/init/all.js2
-rw-r--r--toolkit/components/perfmonitoring/nsPerformanceStats.cpp11
-rw-r--r--toolkit/components/perfmonitoring/nsPerformanceStats.h2
-rw-r--r--toolkit/mozapps/extensions/content/extensions.xml14
70 files changed, 604 insertions, 323 deletions
diff --git a/application/basilisk/components/nsBrowserGlue.js b/application/basilisk/components/nsBrowserGlue.js
index 3258159b6..d77e97f87 100644
--- a/application/basilisk/components/nsBrowserGlue.js
+++ b/application/basilisk/components/nsBrowserGlue.js
@@ -1080,24 +1080,19 @@ BrowserGlue.prototype = {
// For any add-ons that were installed disabled and can be enabled offer
// them to the user.
- let win = RecentWindow.getMostRecentBrowserWindow();
- AddonManager.getAllAddons(addons => {
- for (let addon of addons) {
- // If this add-on has already seen (or seen is undefined for non-XPI
- // add-ons) then skip it.
- if (addon.seen !== false) {
- continue;
- }
-
- // If this add-on cannot be enabled (either already enabled or
- // appDisabled) then skip it.
- if (!(addon.permissions & AddonManager.PERM_CAN_ENABLE)) {
- continue;
- }
-
- win.openUILinkIn("about:newaddon?id=" + addon.id, "tab");
- }
- });
+ let changedIDs = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED);
+ if (changedIDs.length > 0) {
+ let win = this.getMostRecentBrowserWindow();
+ AddonManager.getAddonsByIDs(changedIDs, function(aAddons) {
+ aAddons.forEach(function(aAddon) {
+ // If the add-on isn't user disabled or can't be enabled then skip it.
+ if (!aAddon.userDisabled || !(aAddon.permissions & AddonManager.PERM_CAN_ENABLE))
+ return;
+
+ win.openUILinkIn("about:newaddon?id=" + aAddon.id, "tab");
+ })
+ });
+ }
let signingRequired;
if (AppConstants.MOZ_REQUIRE_SIGNING) {
@@ -1110,6 +1105,11 @@ BrowserGlue.prototype = {
let disabledAddons = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_DISABLED);
AddonManager.getAddonsByIDs(disabledAddons, (addons) => {
for (let addon of addons) {
+ // WEs return null, skip.
+ if (!addon) {
+ continue;
+ }
+
if (addon.type == "experiment")
continue;
diff --git a/application/basilisk/confvars.sh b/application/basilisk/confvars.sh
index 62aa1a84f..cd18bdb94 100644
--- a/application/basilisk/confvars.sh
+++ b/application/basilisk/confvars.sh
@@ -55,7 +55,7 @@ MOZ_APP_STATIC_INI=1
MOZ_WEBGL_CONFORMANT=1
MOZ_JSDOWNLOADS=1
MOZ_WEBRTC=1
-MOZ_WEBEXTENSIONS=1
+MOZ_WEBEXTENSIONS=
MOZ_DEVTOOLS=1
MOZ_SERVICES_COMMON=1
MOZ_SERVICES_SYNC=1
diff --git a/application/palemoon/components/downloads/content/downloads.js b/application/palemoon/components/downloads/content/downloads.js
index ee728406c..ee1c6902e 100644
--- a/application/palemoon/components/downloads/content/downloads.js
+++ b/application/palemoon/components/downloads/content/downloads.js
@@ -1038,9 +1038,9 @@ const DownloadsView = {
}
// We must check for existence synchronously because this is a DOM event.
- let file = new FileUtils.File(DownloadsView.controllerForElement(element)
- .download.target.path);
- if (!file.exists()) {
+ let localFile = new FileUtils.File(DownloadsView.controllerForElement(element)
+ .download.target.path);
+ if (!localFile.exists()) {
return;
}
diff --git a/application/palemoon/components/nsBrowserGlue.js b/application/palemoon/components/nsBrowserGlue.js
index f0a7aa22a..78b14a2e4 100644
--- a/application/palemoon/components/nsBrowserGlue.js
+++ b/application/palemoon/components/nsBrowserGlue.js
@@ -58,8 +58,8 @@ const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
// We try to backup bookmarks at idle times, to avoid doing that at shutdown.
-// Number of idle seconds before trying to backup bookmarks. 15 minutes.
-const BOOKMARKS_BACKUP_IDLE_TIME = 15 * 60;
+// Number of idle seconds before trying to backup bookmarks. 10 minutes.
+const BOOKMARKS_BACKUP_IDLE_TIME = 10 * 60;
// Minimum interval in milliseconds between backups.
const BOOKMARKS_BACKUP_INTERVAL = 86400 * 1000;
// Maximum number of backups to create. Old ones will be purged.
@@ -238,9 +238,9 @@ BrowserGlue.prototype = {
this._onPlacesShutdown();
break;
case "idle":
- if ((this._idleService.idleTime > BOOKMARKS_BACKUP_IDLE_TIME * 1000) &&
- this._shouldBackupBookmarks())
+ if (this._idleService.idleTime > BOOKMARKS_BACKUP_IDLE_TIME * 1000) {
this._backupBookmarks();
+ }
break;
case "distribution-customization-complete":
Services.obs.removeObserver(this, "distribution-customization-complete");
@@ -552,14 +552,6 @@ BrowserGlue.prototype = {
this._showPlacesLockedNotificationBox();
}
- // If there are plugins installed that are outdated, and the user hasn't
- // been warned about them yet, open the plugins update page.
- // Pale Moon: disable this functionality, people are already notified
- // if they visit a page with an outdated plugin, and they can check
- // properly from the plugins page as well.
-// if (Services.prefs.getBoolPref(PREF_PLUGINS_NOTIFYUSER))
-// this._showPluginUpdatePage();
-
// For any add-ons that were installed disabled and can be enabled offer
// them to the user.
let changedIDs = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED);
@@ -949,8 +941,7 @@ BrowserGlue.prototype = {
Services.prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks");
if (restoreDefaultBookmarks) {
// Ensure that we already have a bookmarks backup for today.
- if (this._shouldBackupBookmarks())
- yield this._backupBookmarks();
+ yield this._backupBookmarks();
importBookmarks = true;
}
} catch(ex) {}
@@ -959,7 +950,7 @@ BrowserGlue.prototype = {
// from bookmarks.html, we will try to restore from JSON/JSONLZ4
if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
// get latest JSON/JSONLZ4 backup
- var bookmarksBackupFile = yield PlacesBackups.getMostRecentBackup();
+ var bookmarksBackupFile = PlacesBackups.getMostRecentBackup();
if (bookmarksBackupFile) {
// restore from JSON/JSONLZ4 backup
yield BookmarkJSONUtils.importFromFile(bookmarksBackupFile, true);
@@ -1102,75 +1093,60 @@ BrowserGlue.prototype = {
}
let waitingForBackupToComplete = true;
- if (this._shouldBackupBookmarks()) {
- waitingForBackupToComplete = false;
- this._backupBookmarks().then(
- function onSuccess() {
- waitingForBackupToComplete = true;
- },
- function onFailure() {
- Cu.reportError("Unable to backup bookmarks.");
- waitingForBackupToComplete = true;
- }
- );
- }
+ this._backupBookmarks().then(
+ function onSuccess() {
+ waitingForBackupToComplete = false;
+ },
+ function onFailure() {
+ Cu.reportError("Unable to backup bookmarks.");
+ waitingForBackupToComplete = false;
+ }
+ );
// Backup bookmarks to bookmarks.html to support apps that depend
// on the legacy format.
- let waitingForHTMLExportToComplete = true;
- // If this fails to get the preference value, we don't export.
+ let waitingForHTMLExportToComplete = false;
if (Services.prefs.getBoolPref("browser.bookmarks.autoExportHTML")) {
- // Exceptionally, since this is a non-default setting and HTML format is
- // discouraged in favor of the JSON/JSONLZ4 backups, we spin the event
- // loop on shutdown, to wait for the export to finish. We cannot safely
- // spin the event loop on shutdown until we include a watchdog to prevent
- // potential hangs (bug 518683). The asynchronous shutdown operations
- // will then be handled by a shutdown service (bug 435058).
- waitingForHTMLExportToComplete = false;
+ // Exporting to HTML is explicitly enabled.
+ // We spin the event loop on shutdown, to wait for the export to finish.
+ waitingForHTMLExportToComplete = true;
BookmarkHTMLUtils.exportToFile(BookmarkHTMLUtils.defaultPath).then(
function onSuccess() {
- waitingForHTMLExportToComplete = true;
+ waitingForHTMLExportToComplete = false;
},
function onFailure() {
Cu.reportError("Unable to auto export html.");
- waitingForHTMLExportToComplete = true;
+ waitingForHTMLExportToComplete = false;
}
);
}
+ // The events loop should spin at least once because waitingForBackupToComplete
+ // is true before checking whether backup should be made.
let thread = Services.tm.currentThread;
- while (!waitingForBackupToComplete || !waitingForHTMLExportToComplete) {
+ while (waitingForBackupToComplete || waitingForHTMLExportToComplete) {
thread.processNextEvent(true);
}
},
/**
- * Determine whether to backup bookmarks or not.
- * @return true if bookmarks should be backed up, false if not.
- */
- _shouldBackupBookmarks: function BG__shouldBackupBookmarks() {
- let lastBackupFile = PlacesBackups.getMostRecent();
-
- // Should backup bookmarks if there are no backups or the maximum interval between
- // backups elapsed.
- return (!lastBackupFile ||
- new Date() - PlacesBackups.getDateForFile(lastBackupFile) > BOOKMARKS_BACKUP_INTERVAL);
- },
-
- /**
* Backup bookmarks.
*/
_backupBookmarks: function BG__backupBookmarks() {
return Task.spawn(function() {
- // Backup bookmarks if there are no backups or the maximum interval between
- // backups elapsed.
- let maxBackups = BOOKMARKS_BACKUP_MAX_BACKUPS;
- try {
- maxBackups = Services.prefs.getIntPref("browser.bookmarks.max_backups");
- }
- catch(ex) { /* Use default. */ }
+ let lastBackupFile = yield PlacesBackups.getMostRecentBackup();
+ // We should backup bookmarks if there are no backups or the maximum
+ // interval between backups has lapsed.
+ let hasLapsed = (new Date() - PlacesBackups.getDateForFile(lastBackupFile)) > BOOKMARKS_BACKUP_INTERVAL;
+ if (!lastBackupFile || hasLapsed) {
+ let maxBackups = BOOKMARKS_BACKUP_MAX_BACKUPS;
+ try {
+ maxBackups = Services.prefs.getIntPref("browser.bookmarks.max_backups");
+ }
+ catch(ex) { /* Use default. */ }
- yield PlacesBackups.create(maxBackups); // Don't force creation.
+ yield PlacesBackups.create(maxBackups); // Don't force creation.
+ }
});
},
diff --git a/application/palemoon/themes/linux/browser.css b/application/palemoon/themes/linux/browser.css
index 516677fe6..b545b06cb 100644
--- a/application/palemoon/themes/linux/browser.css
+++ b/application/palemoon/themes/linux/browser.css
@@ -1781,9 +1781,9 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio.svg#tab-audio-blocked");
}
-#TabsToolbar[brighttext] .tab-icon-sound[soundplaying],
-#TabsToolbar[brighttext] .tab-icon-sound[blocked],
-#TabsToolbar[brighttext] .tab-icon-sound[muted] {
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[soundplaying],
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[blocked],
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[muted] {
filter: invert(1);
}
@@ -1827,17 +1827,17 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-blocked");
}
-#TabsToolbar[brighttext] .tab-icon-overlay[soundplaying]:not([selected]):not(:hover),
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[soundplaying]:not([selected]):not(:hover),
.tab-icon-overlay[soundplaying][selected]:-moz-lwtheme-brighttext:not(:hover) {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white");
}
-#TabsToolbar[brighttext] .tab-icon-overlay[muted]:not([crashed]):not([selected]):not(:hover),
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[muted]:not([crashed]):not([selected]):not(:hover),
.tab-icon-overlay[muted][selected]:-moz-lwtheme-brighttext:not(:hover) {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-muted");
}
-#TabsToolbar[brighttext] .tab-icon-overlay[blocked]:not([crashed]):not([selected]):not(:hover),
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[blocked]:not([crashed]):not([selected]):not(:hover),
.tab-icon-overlay[blocked][selected]:-moz-lwtheme-brighttext:not(:hover) {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-blocked");
}
diff --git a/application/palemoon/themes/osx/browser.css b/application/palemoon/themes/osx/browser.css
index a7bd683bd..ddf050785 100644
--- a/application/palemoon/themes/osx/browser.css
+++ b/application/palemoon/themes/osx/browser.css
@@ -1844,9 +1844,9 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio.svg#tab-audio-blocked");
}
-#TabsToolbar[brighttext] .tab-icon-sound[soundplaying],
-#TabsToolbar[brighttext] .tab-icon-sound[blocked],
-#TabsToolbar[brighttext] .tab-icon-sound[muted] {
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[soundplaying],
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[blocked],
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[muted] {
filter: invert(1);
}
@@ -1890,17 +1890,17 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-blocked");
}
-#TabsToolbar[brighttext] .tab-icon-overlay[soundplaying]:not([selected]):not(:hover),
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[soundplaying]:not([selected]):not(:hover),
.tab-icon-overlay[soundplaying][selected]:-moz-lwtheme-brighttext:not(:hover) {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white");
}
-#TabsToolbar[brighttext] .tab-icon-overlay[muted]:not([crashed]):not([selected]):not(:hover),
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[muted]:not([crashed]):not([selected]):not(:hover),
.tab-icon-overlay[muted][selected]:-moz-lwtheme-brighttext:not(:hover) {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-muted");
}
-#TabsToolbar[brighttext] .tab-icon-overlay[blocked]:not([crashed]):not([selected]):not(:hover),
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[blocked]:not([crashed]):not([selected]):not(:hover),
.tab-icon-overlay[blocked][selected]:-moz-lwtheme-brighttext:not(:hover) {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-blocked");
}
diff --git a/application/palemoon/themes/windows/browser.css b/application/palemoon/themes/windows/browser.css
index c261fe083..56a8318da 100644
--- a/application/palemoon/themes/windows/browser.css
+++ b/application/palemoon/themes/windows/browser.css
@@ -2050,9 +2050,9 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio.svg#tab-audio-blocked");
}
-#TabsToolbar[brighttext] .tab-icon-sound[soundplaying],
-#TabsToolbar[brighttext] .tab-icon-sound[blocked],
-#TabsToolbar[brighttext] .tab-icon-sound[muted] {
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[soundplaying],
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[blocked],
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-sound[muted] {
filter: invert(1);
}
@@ -2096,17 +2096,17 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-blocked");
}
-#TabsToolbar[brighttext] .tab-icon-overlay[soundplaying]:not([selected]):not(:hover),
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[soundplaying]:not([selected]):not(:hover),
.tab-icon-overlay[soundplaying][selected]:-moz-lwtheme-brighttext:not(:hover) {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white");
}
-#TabsToolbar[brighttext] .tab-icon-overlay[muted]:not([crashed]):not([selected]):not(:hover),
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[muted]:not([crashed]):not([selected]):not(:hover),
.tab-icon-overlay[muted][selected]:-moz-lwtheme-brighttext:not(:hover) {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-muted");
}
-#TabsToolbar[brighttext] .tab-icon-overlay[blocked]:not([crashed]):not([selected]):not(:hover),
+#TabsToolbar:-moz-lwtheme-brighttext .tab-icon-overlay[blocked]:not([crashed]):not([selected]):not(:hover),
.tab-icon-overlay[blocked][selected]:-moz-lwtheme-brighttext:not(:hover) {
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-blocked");
}
diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp
index ecea95dc1..75d408151 100644
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -297,6 +297,16 @@ nsNodeUtils::LastRelease(nsINode* aNode)
NodeWillBeDestroyed, (aNode));
}
+ if (aNode->IsElement()) {
+ Element* elem = aNode->AsElement();
+ FragmentOrElement::nsDOMSlots* domSlots =
+ static_cast<FragmentOrElement::nsDOMSlots*>(slots);
+ for (auto iter = domSlots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
+ DOMIntersectionObserver* observer = iter.Key();
+ observer->UnlinkTarget(*elem);
+ }
+ }
+
delete slots;
aNode->mSlots = nullptr;
}
diff --git a/dom/webidl/IntersectionObserver.webidl b/dom/webidl/IntersectionObserver.webidl
index bc193ee8c..83200d950 100644
--- a/dom/webidl/IntersectionObserver.webidl
+++ b/dom/webidl/IntersectionObserver.webidl
@@ -7,7 +7,7 @@
* https://wicg.github.io/IntersectionObserver/
*/
-[ProbablyShortLivingObject, Pref="dom.IntersectionObserver.enabled"]
+[ProbablyShortLivingObject, Pref="dom.intersectionObserver.enabled"]
interface IntersectionObserverEntry {
[Constant]
readonly attribute DOMHighResTimeStamp time;
@@ -27,7 +27,7 @@ interface IntersectionObserverEntry {
[Constructor(IntersectionCallback intersectionCallback,
optional IntersectionObserverInit options),
- Pref="dom.IntersectionObserver.enabled"]
+ Pref="dom.intersectionObserver.enabled"]
interface IntersectionObserver {
[Constant]
readonly attribute Element? root;
diff --git a/image/IDecodingTask.cpp b/image/IDecodingTask.cpp
index a067e7a7d..6e2f039be 100644
--- a/image/IDecodingTask.cpp
+++ b/image/IDecodingTask.cpp
@@ -142,8 +142,10 @@ MetadataDecodingTask::Run()
// AnonymousDecodingTask implementation.
///////////////////////////////////////////////////////////////////////////////
-AnonymousDecodingTask::AnonymousDecodingTask(NotNull<Decoder*> aDecoder)
+AnonymousDecodingTask::AnonymousDecodingTask(NotNull<Decoder*> aDecoder,
+ bool aResumable)
: mDecoder(aDecoder)
+ , mResumable(aResumable)
{ }
void
@@ -168,5 +170,16 @@ AnonymousDecodingTask::Run()
}
}
+void
+AnonymousDecodingTask::Resume()
+{
+ // Anonymous decoders normally get all their data at once. We have some situations
+ // where they don't. If explicitly requested, resuming should be supported.
+ if (mResumable) {
+ RefPtr<AnonymousDecodingTask> self(this);
+ NS_DispatchToMainThread(NS_NewRunnableFunction([self]() -> void { self->Run(); }));
+ }
+}
+
} // namespace image
} // namespace mozilla
diff --git a/image/IDecodingTask.h b/image/IDecodingTask.h
index 196ce5fdc..3cbab5006 100644
--- a/image/IDecodingTask.h
+++ b/image/IDecodingTask.h
@@ -102,22 +102,20 @@ class AnonymousDecodingTask final : public IDecodingTask
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnonymousDecodingTask, override)
- explicit AnonymousDecodingTask(NotNull<Decoder*> aDecoder);
+ explicit AnonymousDecodingTask(NotNull<Decoder*> aDecoder, bool aResumable);
void Run() override;
bool ShouldPreferSyncRun() const override { return true; }
TaskPriority Priority() const override { return TaskPriority::eLow; }
- // Anonymous decoders normally get all their data at once. We have tests where
- // they don't; in these situations, the test re-runs them manually. So no
- // matter what, we don't want to resume by posting a task to the DecodePool.
- void Resume() override { }
+ void Resume() override;
private:
virtual ~AnonymousDecodingTask() { }
NotNull<RefPtr<Decoder>> mDecoder;
+ bool mResumable;
};
} // namespace image
diff --git a/image/ImageOps.cpp b/image/ImageOps.cpp
index addee7f15..ddd2f200e 100644
--- a/image/ImageOps.cpp
+++ b/image/ImageOps.cpp
@@ -126,7 +126,7 @@ ImageOps::DecodeToSurface(nsIInputStream* aInputStream,
}
// Run the decoder synchronously.
- RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder));
+ RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false);
task->Run();
if (!decoder->GetDecodeDone() || decoder->HasError()) {
return nullptr;
diff --git a/image/SourceBuffer.cpp b/image/SourceBuffer.cpp
index de0719d45..de066e29f 100644
--- a/image/SourceBuffer.cpp
+++ b/image/SourceBuffer.cpp
@@ -451,10 +451,18 @@ SourceBuffer::AppendFromInputStream(nsIInputStream* aInputStream,
uint32_t bytesRead;
nsresult rv = aInputStream->ReadSegments(AppendToSourceBuffer, this,
aCount, &bytesRead);
- if (!NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_ASSERT(bytesRead == aCount,
- "AppendToSourceBuffer should consume everything");
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ if (bytesRead == 0) {
+ // The loading of the image has been canceled.
+ return NS_ERROR_FAILURE;
}
+
+ MOZ_ASSERT(bytesRead == aCount,
+ "AppendToSourceBuffer should consume everything");
+
return rv;
}
diff --git a/image/SourceBuffer.h b/image/SourceBuffer.h
index 64727e65e..6f2c74d33 100644
--- a/image/SourceBuffer.h
+++ b/image/SourceBuffer.h
@@ -174,6 +174,13 @@ public:
return mState == READY ? mData.mIterating.mNextReadLength : 0;
}
+ /// If we're ready to read, returns whether or not everything available thus
+ /// far has been in the same contiguous buffer.
+ bool IsContiguous() const {
+ MOZ_ASSERT(mState == READY, "Calling IsContiguous() in the wrong state");
+ return mState == READY ? mData.mIterating.mChunk == 0 : false;
+ }
+
/// @return a count of the chunks we've advanced through.
uint32_t ChunkCount() const { return mChunkCount; }
diff --git a/image/decoders/nsWebPDecoder.cpp b/image/decoders/nsWebPDecoder.cpp
index 4f3cc8b2a..3181e3a3a 100644
--- a/image/decoders/nsWebPDecoder.cpp
+++ b/image/decoders/nsWebPDecoder.cpp
@@ -144,6 +144,10 @@ nsWebPDecoder::UpdateBuffer(SourceBufferIterator& aIterator,
switch (aState) {
case SourceBufferIterator::READY:
+ if(!aIterator.IsContiguous()) {
+ //We need to buffer. This should be rare, but expensive.
+ break;
+ }
if (!mData) {
// For as long as we hold onto an iterator, we know the data pointers
// to the chunks cannot change underneath us, so save the pointer to
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 0983f034f..799396a0a 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -6566,7 +6566,7 @@ struct JS_PUBLIC_API(PerformanceGroup) {
uint64_t refCount_;
};
-using PerformanceGroupVector = mozilla::Vector<RefPtr<js::PerformanceGroup>, 0, SystemAllocPolicy>;
+using PerformanceGroupVector = mozilla::Vector<RefPtr<js::PerformanceGroup>, 8, SystemAllocPolicy>;
/**
* Commit any Performance Monitoring data.
diff --git a/js/src/vm/Stopwatch.cpp b/js/src/vm/Stopwatch.cpp
index 7a6acb970..5b5ec6196 100644
--- a/js/src/vm/Stopwatch.cpp
+++ b/js/src/vm/Stopwatch.cpp
@@ -20,6 +20,7 @@
#include "gc/Zone.h"
#include "vm/Runtime.h"
+
namespace js {
bool
@@ -136,6 +137,9 @@ PerformanceMonitoring::start()
bool
PerformanceMonitoring::commit()
{
+ // Maximal initialization size, in elements for the vector of groups.
+ static const size_t MAX_GROUPS_INIT_CAPACITY = 1024;
+
#if !defined(MOZ_HAVE_RDTSC)
// The AutoStopwatch is only executed if `MOZ_HAVE_RDTSC`.
return false;
@@ -152,13 +156,24 @@ PerformanceMonitoring::commit()
return true;
}
- PerformanceGroupVector recentGroups;
- recentGroups_.swap(recentGroups);
+ // The move operation is generally constant time, unless
+ // `recentGroups_.length()` is very small, in which case
+ // it's fast just because it's small.
+ PerformanceGroupVector recentGroups(Move(recentGroups_));
+ recentGroups_ = PerformanceGroupVector(); // Reconstruct after `Move`.
bool success = true;
if (stopwatchCommitCallback)
success = stopwatchCommitCallback(iteration_, recentGroups, stopwatchCommitClosure);
+ // Heuristic: we expect to have roughly the same number of groups as in
+ // the previous iteration.
+ const size_t capacity = recentGroups.capacity() < MAX_GROUPS_INIT_CAPACITY ?
+ recentGroups.capacity() :
+ MAX_GROUPS_INIT_CAPACITY;
+ success = recentGroups_.reserve(capacity)
+ && success;
+
// Reset immediately, to make sure that we're not hit by the end
// of a nested event loop (which would cause `commit` to be called
// twice in succession).
@@ -227,7 +242,7 @@ AutoStopwatch::AutoStopwatch(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IM
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
JSCompartment* compartment = cx_->compartment();
- if (compartment->scheduledForDestruction)
+ if (MOZ_UNLIKELY(compartment->scheduledForDestruction))
return;
JSRuntime* runtime = cx_->runtime();
@@ -266,11 +281,11 @@ AutoStopwatch::~AutoStopwatch()
}
JSCompartment* compartment = cx_->compartment();
- if (compartment->scheduledForDestruction)
+ if (MOZ_UNLIKELY(compartment->scheduledForDestruction))
return;
JSRuntime* runtime = cx_->runtime();
- if (iteration_ != runtime->performanceMonitoring.iteration()) {
+ if (MOZ_UNLIKELY(iteration_ != runtime->performanceMonitoring.iteration())) {
// We have entered a nested event loop at some point.
// Any information we may have is obsolete.
return;
diff --git a/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp b/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp
index 37bb2b7a5..f1c797c9a 100644
--- a/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp
@@ -321,7 +321,18 @@ status_t SampleIterator::findSampleTime(
*time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);
- *time += mTable->getCompositionTimeOffset(sampleIndex);
+ int32_t offset = mTable->getCompositionTimeOffset(sampleIndex);
+ if ((offset < 0 && *time < (offset == INT32_MIN ?
+ INT32_MAX : uint32_t(-offset))) ||
+ (offset > 0 && *time > UINT32_MAX - offset)) {
+ ALOGE("%u + %d would overflow", *time, offset);
+ return ERROR_OUT_OF_RANGE;
+ }
+ if (offset > 0) {
+ *time += offset;
+ } else {
+ *time -= (offset == INT32_MIN ? INT32_MAX : (-offset));
+ }
return OK;
}
diff --git a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
index bbb2227e7..bc991e8e1 100644
--- a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
@@ -52,14 +52,14 @@ struct SampleTable::CompositionDeltaLookup {
CompositionDeltaLookup();
void setEntries(
- const uint32_t *deltaEntries, size_t numDeltaEntries);
+ const int32_t *deltaEntries, size_t numDeltaEntries);
- uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
+ int32_t getCompositionTimeOffset(uint32_t sampleIndex);
private:
Mutex mLock;
- const uint32_t *mDeltaEntries;
+ const int32_t *mDeltaEntries;
size_t mNumDeltaEntries;
size_t mCurrentDeltaEntry;
@@ -76,7 +76,7 @@ SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
}
void SampleTable::CompositionDeltaLookup::setEntries(
- const uint32_t *deltaEntries, size_t numDeltaEntries) {
+ const int32_t *deltaEntries, size_t numDeltaEntries) {
Mutex::Autolock autolock(mLock);
mDeltaEntries = deltaEntries;
@@ -85,7 +85,7 @@ void SampleTable::CompositionDeltaLookup::setEntries(
mCurrentEntrySampleIndex = 0;
}
-uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
+int32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
uint32_t sampleIndex) {
Mutex::Autolock autolock(mLock);
@@ -381,6 +381,10 @@ status_t SampleTable::setTimeToSampleParams(
return OK;
}
+// NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1
+// contains signed values, however some software creates version 0 files that
+// contain signed values, so we're always treating the values as signed,
+// regardless of version.
status_t SampleTable::setCompositionTimeToSampleParams(
off64_t data_offset, size_t data_size) {
ALOGV("There are reordered frames present.");
@@ -398,8 +402,12 @@ status_t SampleTable::setCompositionTimeToSampleParams(
uint32_t numEntries = U32_AT(&header[4]);
- if (U32_AT(header) != 0 && numEntries) {
- // Expected version = 0, flags = 0.
+ uint32_t flags = U32_AT(header);
+ uint32_t version = flags >> 24;
+ flags &= 0xffffff;
+
+ if ((version != 0 && version != 1) || flags != 0) {
+ // Expected version = 0 or 1, flags = 0.
return ERROR_MALFORMED;
}
@@ -408,7 +416,7 @@ status_t SampleTable::setCompositionTimeToSampleParams(
}
mNumCompositionTimeDeltaEntries = numEntries;
- mCompositionTimeDeltaEntries = new (mozilla::fallible) uint32_t[2 * numEntries];
+ mCompositionTimeDeltaEntries = new (mozilla::fallible) int32_t[2 * numEntries];
if (!mCompositionTimeDeltaEntries) {
return ERROR_BUFFER_TOO_SMALL;
}
@@ -801,12 +809,28 @@ status_t SampleTable::buildSampleEntriesTable() {
mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
- uint32_t compTimeDelta =
+ int32_t compTimeDelta =
mCompositionDeltaLookup->getCompositionTimeOffset(
sampleIndex);
+ if ((compTimeDelta < 0 && sampleTime <
+ (compTimeDelta == INT32_MIN ?
+ INT32_MAX : uint32_t(-compTimeDelta)))
+ || (compTimeDelta > 0 &&
+ sampleTime > UINT32_MAX - compTimeDelta)) {
+ ALOGE("%u + %d would overflow, clamping",
+ sampleTime, compTimeDelta);
+ if (compTimeDelta < 0) {
+ sampleTime = 0;
+ } else {
+ sampleTime = UINT32_MAX;
+ }
+ compTimeDelta = 0;
+ }
+
mSampleTimeEntries[sampleIndex].mCompositionTime =
- sampleTime + compTimeDelta;
+ compTimeDelta > 0 ? sampleTime + compTimeDelta:
+ sampleTime - (-compTimeDelta);
}
++sampleIndex;
@@ -1136,7 +1160,7 @@ status_t SampleTable::getMetaDataForSample(
return OK;
}
-uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
+int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
}
diff --git a/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h b/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h
index e115c92bb..c235f281e 100644
--- a/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h
@@ -134,7 +134,7 @@ private:
};
SampleTimeEntry *mSampleTimeEntries;
- uint32_t *mCompositionTimeDeltaEntries;
+ int32_t *mCompositionTimeDeltaEntries;
size_t mNumCompositionTimeDeltaEntries;
CompositionDeltaLookup *mCompositionDeltaLookup;
@@ -171,7 +171,7 @@ private:
friend struct SampleIterator;
status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
- uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
+ int32_t getCompositionTimeOffset(uint32_t sampleIndex);
static int CompareIncreasingTime(const void *, const void *);
diff --git a/media/libwebp/AUTHORS b/media/libwebp/AUTHORS
index 83c7b9c5e..0d70b7fb2 100644
--- a/media/libwebp/AUTHORS
+++ b/media/libwebp/AUTHORS
@@ -1,4 +1,5 @@
Contributors:
+- Alan Browning (browning at google dot com)
- Charles Munger (clm at google dot com)
- Christian Duvivier (cduvivier at google dot com)
- Djordje Pesut (djordje dot pesut at imgtec dot com)
@@ -6,9 +7,10 @@ Contributors:
- James Zern (jzern at google dot com)
- Jan Engelhardt (jengelh at medozas dot de)
- Jehan (jehan at girinstud dot io)
-- Johann (johann dot koenig at duck dot com)
+- Johann Koenig (johann dot koenig at duck dot com)
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
- Jyrki Alakuijala (jyrki at google dot com)
+- Konstantin Ivlev (tomskside at gmail dot com)
- Lode Vandevenne (lode at google dot com)
- Lou Quillio (louquillio at google dot com)
- Mans Rullgard (mans at mansr dot com)
@@ -37,3 +39,4 @@ Contributors:
- Vincent Rabaud (vrabaud at google dot com)
- Vlad Tsyrklevich (vtsyrklevich at chromium dot org)
- Yang Zhang (yang dot zhang at arm dot com)
+- Yannis Guyon (yguyon at google dot com)
diff --git a/media/libwebp/NEWS b/media/libwebp/NEWS
index 480cb7d34..aa393c819 100644
--- a/media/libwebp/NEWS
+++ b/media/libwebp/NEWS
@@ -1,3 +1,23 @@
+- 1/14/2019: version 1.0.2
+ This is a binary compatible release.
+ * (Windows) unicode file support in the tools (linux and mac already had
+ support, issue #398)
+ * lossless encoder speedups
+ * lossy encoder speedup on ARM
+ * lossless multi-threaded security fix (chromium:917029)
+
+- 11/2/2018: version 1.0.1
+ This is a binary compatible release.
+ * lossless encoder speedups
+ * big-endian fix for alpha decoding (issue #393)
+ * gif2webp fix for loop count=65535 transcode (issue #382)
+ * further security related hardening in libwebp & libwebpmux
+ (issues #383, #385, #386, #387, #388, #391)
+ (oss-fuzz #9099, #9100, #9105, #9106, #9111, #9112, #9119, #9123, #9170,
+ #9178, #9179, #9183, #9186, #9191, #9364, #9417, #9496, #10349,
+ #10423, #10634, #10700, #10838, #10922, #11021, #11088, #11152)
+ * miscellaneous bug & build fixes (issues #381, #394, #396, #397, #400)
+
- 4/2/2018: version 1.0.0
This is a binary compatible release.
* lossy encoder improvements to avoid chroma shifts in various circumstances
diff --git a/media/libwebp/README b/media/libwebp/README
index a76b3787f..502a4c1c2 100644
--- a/media/libwebp/README
+++ b/media/libwebp/README
@@ -4,7 +4,7 @@
\__\__/\____/\_____/__/ ____ ___
/ _/ / \ \ / _ \/ _/
/ \_/ / / \ \ __/ \__
- \____/____/\_____/_____/____/v1.0.0
+ \____/____/\_____/_____/____/v1.0.2
Description:
============
@@ -136,6 +136,8 @@ cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../
or through your favorite interface (like ccmake or cmake-qt-gui).
+Use option -DWEBP_UNICODE=ON for Unicode support on Windows (with chcp 65001).
+
Finally, once installed, you can also use WebP in your CMake project by doing:
find_package(WebP)
@@ -402,12 +404,14 @@ Options are:
-nofilter .... disable in-loop filtering
-dither <int> dithering strength (0..100), default=50
-noalphadither disable alpha plane dithering
+ -usebgcolor .. display background color
-mt .......... use multi-threading
-info ........ print info
-h ........... this help message
Keyboard shortcuts:
'c' ................ toggle use of color profile
+ 'b' ................ toggle background color display
'i' ................ overlay file information
'd' ................ disable blending & disposal (debug)
'q' / 'Q' / ESC .... quit
@@ -470,6 +474,9 @@ Per-frame options (only used for subsequent images input):
example: img2webp -loop 2 in0.png -lossy in1.jpg
-d 80 in2.tiff -o out.webp
+Note: if a single file name is passed as the argument, the arguments will be
+tokenized from this file. The file name must not start with the character '-'.
+
Animated GIF conversion:
========================
Animated GIF files can be converted to WebP files with animation using the
diff --git a/media/libwebp/README.mux b/media/libwebp/README.mux
index bd4f92fa3..7e9c3c903 100644
--- a/media/libwebp/README.mux
+++ b/media/libwebp/README.mux
@@ -1,7 +1,7 @@
 __ __ ____ ____ ____ __ __ _ __ __
/ \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\
\ / __/ _ \ __/ / / (_/ /__
- \__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.0.0
+ \__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.0.2
Description:
@@ -211,6 +211,35 @@ Code example:
For a detailed AnimEncoder API reference, please refer to the header file
(src/webp/mux.h).
+AnimDecoder API:
+================
+This AnimDecoder API allows decoding (possibly) animated WebP images.
+
+Code Example:
+
+ WebPAnimDecoderOptions dec_options;
+ WebPAnimDecoderOptionsInit(&dec_options);
+ // Tune 'dec_options' as needed.
+ WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options);
+ WebPAnimInfo anim_info;
+ WebPAnimDecoderGetInfo(dec, &anim_info);
+ for (uint32_t i = 0; i < anim_info.loop_count; ++i) {
+ while (WebPAnimDecoderHasMoreFrames(dec)) {
+ uint8_t* buf;
+ int timestamp;
+ WebPAnimDecoderGetNext(dec, &buf, &timestamp);
+ // ... (Render 'buf' based on 'timestamp').
+ // ... (Do NOT free 'buf', as it is owned by 'dec').
+ }
+ WebPAnimDecoderReset(dec);
+ }
+ const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec);
+ // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data).
+ WebPAnimDecoderDelete(dec);
+
+For a detailed AnimDecoder API reference, please refer to the header file
+(src/webp/demux.h).
+
Bugs:
=====
diff --git a/media/libwebp/UXPCHANGES b/media/libwebp/UXPCHANGES
index 8c3eb5ad2..78b7823c8 100644
--- a/media/libwebp/UXPCHANGES
+++ b/media/libwebp/UXPCHANGES
@@ -2,3 +2,4 @@ Changes made to pristine libwebp source by Moonchild Productions and mozilla.org
2017/01/27 -- Synced with libwebp-0.6.0 (BZ #1294490).
2018/06/29 -- Synced with libwebp-1.0.0 + BUG=webp:381,383,384.
+2019/01/21 -- Synced with libwebp-1.0.2
diff --git a/media/libwebp/dec/alphai_dec.h b/media/libwebp/dec/alphai_dec.h
index 3b40691b5..d2a404dc5 100644
--- a/media/libwebp/dec/alphai_dec.h
+++ b/media/libwebp/dec/alphai_dec.h
@@ -51,4 +51,4 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
} // extern "C"
#endif
-#endif /* WEBP_DEC_ALPHAI_DEC_H_ */
+#endif // WEBP_DEC_ALPHAI_DEC_H_
diff --git a/media/libwebp/dec/common_dec.h b/media/libwebp/dec/common_dec.h
index 9995f1a51..b158550a8 100644
--- a/media/libwebp/dec/common_dec.h
+++ b/media/libwebp/dec/common_dec.h
@@ -51,4 +51,4 @@ enum { MB_FEATURE_TREE_PROBS = 3,
NUM_PROBAS = 11
};
-#endif // WEBP_DEC_COMMON_DEC_H_
+#endif // WEBP_DEC_COMMON_DEC_H_
diff --git a/media/libwebp/dec/frame_dec.c b/media/libwebp/dec/frame_dec.c
index 57e4d9669..3d1d66274 100644
--- a/media/libwebp/dec/frame_dec.c
+++ b/media/libwebp/dec/frame_dec.c
@@ -338,7 +338,6 @@ void VP8InitDithering(const WebPDecoderOptions* const options,
for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
VP8QuantMatrix* const dqm = &dec->dqm_[s];
if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) {
- // TODO(skal): should we specially dither more for uv_quant_ < 0?
const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_;
dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3;
}
@@ -669,15 +668,9 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options,
(void)height;
assert(headers == NULL || !headers->is_lossless);
#if defined(WEBP_USE_THREAD)
- if (width < MIN_WIDTH_FOR_THREADS) return 0;
- // TODO(skal): tune the heuristic further
-#if 0
- if (height < 2 * width) return 2;
+ if (width >= MIN_WIDTH_FOR_THREADS) return 2;
#endif
- return 2;
-#else // !WEBP_USE_THREAD
return 0;
-#endif
}
#undef MT_CACHE_LINES
diff --git a/media/libwebp/dec/idec_dec.c b/media/libwebp/dec/idec_dec.c
index c9506bc83..ee0d33eac 100644
--- a/media/libwebp/dec/idec_dec.c
+++ b/media/libwebp/dec/idec_dec.c
@@ -140,10 +140,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
if (NeedCompressedAlpha(idec)) {
ALPHDecoder* const alph_dec = dec->alph_dec_;
dec->alpha_data_ += offset;
- if (alph_dec != NULL) {
+ if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) {
if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) {
VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_;
- assert(alph_vp8l_dec != NULL);
assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN);
VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_,
dec->alpha_data_ + ALPHA_HEADER_LEN,
@@ -449,7 +448,10 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
VP8Io* const io = &idec->io_;
- assert(dec->ready_);
+ // Make sure partition #0 has been read before, to set dec to ready_.
+ if (!dec->ready_) {
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
if (idec->last_mb_y_ != dec->mb_y_) {
if (!VP8ParseIntraModeRow(&dec->br_, dec)) {
@@ -471,6 +473,12 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
}
+ // Synchronize the threads.
+ if (dec->mt_method_ > 0) {
+ if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) {
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
+ }
RestoreContext(&context, dec, token_br);
return VP8_STATUS_SUSPENDED;
}
@@ -489,6 +497,7 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
}
// Synchronize the thread and check for errors.
if (!VP8ExitCritical(dec, io)) {
+ idec->state_ = STATE_ERROR; // prevent re-entry in IDecError
return IDecError(idec, VP8_STATUS_USER_ABORT);
}
dec->ready_ = 0;
@@ -569,6 +578,10 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) {
status = DecodePartition0(idec);
}
if (idec->state_ == STATE_VP8_DATA) {
+ const VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ if (dec == NULL) {
+ return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder.
+ }
status = DecodeRemaining(idec);
}
if (idec->state_ == STATE_VP8L_HEADER) {
diff --git a/media/libwebp/dec/vp8_dec.h b/media/libwebp/dec/vp8_dec.h
index 7b4941d65..03f4415fb 100644
--- a/media/libwebp/dec/vp8_dec.h
+++ b/media/libwebp/dec/vp8_dec.h
@@ -182,4 +182,4 @@ WEBP_EXTERN int VP8LGetInfo(
} // extern "C"
#endif
-#endif /* WEBP_DEC_VP8_DEC_H_ */
+#endif // WEBP_DEC_VP8_DEC_H_
diff --git a/media/libwebp/dec/vp8i_dec.h b/media/libwebp/dec/vp8i_dec.h
index d0ef67b91..fabee44a0 100644
--- a/media/libwebp/dec/vp8i_dec.h
+++ b/media/libwebp/dec/vp8i_dec.h
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 0
-#define DEC_REV_VERSION 0
+#define DEC_REV_VERSION 2
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y),
@@ -316,4 +316,4 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
} // extern "C"
#endif
-#endif /* WEBP_DEC_VP8I_DEC_H_ */
+#endif // WEBP_DEC_VP8I_DEC_H_
diff --git a/media/libwebp/dec/vp8l_dec.c b/media/libwebp/dec/vp8l_dec.c
index 3d303fb22..0502cb9a5 100644
--- a/media/libwebp/dec/vp8l_dec.c
+++ b/media/libwebp/dec/vp8l_dec.c
@@ -359,17 +359,22 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int color_cache_bits, int allow_recursion) {
int i, j;
VP8LBitReader* const br = &dec->br_;
- VP8LBitReader br_tmp;
VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL;
+ // When reading htrees, some might be unused, as the format allows it.
+ // We will still read them but put them in this htree_group_bogus.
+ HTreeGroup htree_group_bogus;
HuffmanCode* huffman_tables = NULL;
+ HuffmanCode* huffman_tables_bogus = NULL;
HuffmanCode* next = NULL;
int num_htree_groups = 1;
- int num_htree_groups_limit = 1;
+ int num_htree_groups_max = 1;
int max_alphabet_size = 0;
int* code_lengths = NULL;
const int table_size = kTableSize[color_cache_bits];
+ int* mapping = NULL;
+ int ok = 0;
if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes.
@@ -386,21 +391,41 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
// The huffman data is stored in red and green bytes.
const int group = (huffman_image[i] >> 8) & 0xffff;
huffman_image[i] = group;
- if (group >= num_htree_groups) {
- num_htree_groups = group + 1;
+ if (group >= num_htree_groups_max) {
+ num_htree_groups_max = group + 1;
}
}
- // Check the validity of num_htree_groups. If it seems too big, use a
+ // Check the validity of num_htree_groups_max. If it seems too big, use a
// smaller value for later. This will prevent big memory allocations to end
// up with a bad bitstream anyway.
- // The value of 1000 is totally arbitrary. We know that num_htree_groups
+ // The value of 1000 is totally arbitrary. We know that num_htree_groups_max
// is smaller than (1 << 16) and should be smaller than the number of pixels
// (though the format allows it to be bigger).
- if (num_htree_groups > 1000 || num_htree_groups > xsize * ysize) {
- num_htree_groups_limit = (xsize * ysize > 1000) ? 1000 : xsize * ysize;
- br_tmp = dec->br_;
+ if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) {
+ // Create a mapping from the used indices to the minimal set of used
+ // values [0, num_htree_groups)
+ mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));
+ if (mapping == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ goto Error;
+ }
+ // -1 means a value is unmapped, and therefore unused in the Huffman
+ // image.
+ memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping));
+ for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) {
+ // Get the current mapping for the group and remap the Huffman image.
+ int* const mapped_group = &mapping[huffman_image[i]];
+ if (*mapped_group == -1) *mapped_group = num_htree_groups++;
+ huffman_image[i] = *mapped_group;
+ }
+ huffman_tables_bogus = (HuffmanCode*)WebPSafeMalloc(
+ table_size, sizeof(*huffman_tables_bogus));
+ if (huffman_tables_bogus == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ goto Error;
+ }
} else {
- num_htree_groups_limit = num_htree_groups;
+ num_htree_groups = num_htree_groups_max;
}
}
@@ -419,99 +444,91 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size,
sizeof(*code_lengths));
- // If num_htree_groups_tmp == num_htree_groups, the following loop is executed
- // once.
- // If num_htree_groups_tmp != num_htree_groups, we execute the loop the first
- // time with little memory allocation in the hope that there is a bitstream
- // error. If after num_htree_groups_tmp iterations, no error appears,
- // num_htree_groups is probably the right value so try it out.
- do {
- huffman_tables = (HuffmanCode*)WebPSafeMalloc(
- num_htree_groups_limit * table_size, sizeof(*huffman_tables));
- htree_groups = VP8LHtreeGroupsNew(num_htree_groups_limit);
-
- if (htree_groups == NULL || code_lengths == NULL ||
- huffman_tables == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- goto Error;
- }
+ huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size,
+ sizeof(*huffman_tables));
+ htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
- next = huffman_tables;
- for (i = 0; i < num_htree_groups_limit; ++i) {
- HTreeGroup* const htree_group = &htree_groups[i];
- HuffmanCode** const htrees = htree_group->htrees;
- int size;
- int total_size = 0;
- int is_trivial_literal = 1;
- int max_bits = 0;
- for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
- int alphabet_size = kAlphabetSize[j];
- htrees[j] = next;
- if (j == 0 && color_cache_bits > 0) {
- alphabet_size += 1 << color_cache_bits;
- }
- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next);
- if (size == 0) {
- goto Error;
- }
- if (is_trivial_literal && kLiteralMap[j] == 1) {
- is_trivial_literal = (next->bits == 0);
- }
- total_size += next->bits;
- next += size;
- if (j <= ALPHA) {
- int local_max_bits = code_lengths[0];
- int k;
- for (k = 1; k < alphabet_size; ++k) {
- if (code_lengths[k] > local_max_bits) {
- local_max_bits = code_lengths[k];
- }
- }
- max_bits += local_max_bits;
- }
+ if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) {
+ dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ next = huffman_tables;
+ for (i = 0; i < num_htree_groups_max; ++i) {
+ // If the index "i" is unused in the Huffman image, read the coefficients
+ // but store them to a bogus htree_group.
+ const int is_bogus = (mapping != NULL && mapping[i] == -1);
+ HTreeGroup* const htree_group =
+ is_bogus ? &htree_group_bogus :
+ &htree_groups[(mapping == NULL) ? i : mapping[i]];
+ HuffmanCode** const htrees = htree_group->htrees;
+ HuffmanCode* huffman_tables_i = is_bogus ? huffman_tables_bogus : next;
+ int size;
+ int total_size = 0;
+ int is_trivial_literal = 1;
+ int max_bits = 0;
+ for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
+ int alphabet_size = kAlphabetSize[j];
+ htrees[j] = huffman_tables_i;
+ if (j == 0 && color_cache_bits > 0) {
+ alphabet_size += 1 << color_cache_bits;
}
- htree_group->is_trivial_literal = is_trivial_literal;
- htree_group->is_trivial_code = 0;
- if (is_trivial_literal) {
- const int red = htrees[RED][0].value;
- const int blue = htrees[BLUE][0].value;
- const int alpha = htrees[ALPHA][0].value;
- htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
- if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
- htree_group->is_trivial_code = 1;
- htree_group->literal_arb |= htrees[GREEN][0].value << 8;
+ size =
+ ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables_i);
+ if (size == 0) {
+ goto Error;
+ }
+ if (is_trivial_literal && kLiteralMap[j] == 1) {
+ is_trivial_literal = (huffman_tables_i->bits == 0);
+ }
+ total_size += huffman_tables_i->bits;
+ huffman_tables_i += size;
+ if (j <= ALPHA) {
+ int local_max_bits = code_lengths[0];
+ int k;
+ for (k = 1; k < alphabet_size; ++k) {
+ if (code_lengths[k] > local_max_bits) {
+ local_max_bits = code_lengths[k];
+ }
}
+ max_bits += local_max_bits;
}
- htree_group->use_packed_table =
- !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
- if (htree_group->use_packed_table) BuildPackedTable(htree_group);
}
- // If we have survived up to here, num_htree_groups might actually be
- // that big so restart with a proper allocation.
- if (num_htree_groups != num_htree_groups_limit) {
- num_htree_groups_limit = num_htree_groups;
- WebPSafeFree(huffman_tables);
- VP8LHtreeGroupsFree(htree_groups);
- huffman_tables = NULL;
- htree_groups = NULL;
- dec->br_ = br_tmp;
+ if (!is_bogus) next = huffman_tables_i;
+ htree_group->is_trivial_literal = is_trivial_literal;
+ htree_group->is_trivial_code = 0;
+ if (is_trivial_literal) {
+ const int red = htrees[RED][0].value;
+ const int blue = htrees[BLUE][0].value;
+ const int alpha = htrees[ALPHA][0].value;
+ htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
+ if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
+ htree_group->is_trivial_code = 1;
+ htree_group->literal_arb |= htrees[GREEN][0].value << 8;
+ }
}
- } while (i != num_htree_groups);
- WebPSafeFree(code_lengths);
+ htree_group->use_packed_table =
+ !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
+ if (htree_group->use_packed_table) BuildPackedTable(htree_group);
+ }
+ ok = 1;
- // All OK. Finalize pointers and return.
+ // All OK. Finalize pointers.
hdr->huffman_image_ = huffman_image;
hdr->num_htree_groups_ = num_htree_groups;
hdr->htree_groups_ = htree_groups;
hdr->huffman_tables_ = huffman_tables;
- return 1;
Error:
WebPSafeFree(code_lengths);
- WebPSafeFree(huffman_image);
- WebPSafeFree(huffman_tables);
- VP8LHtreeGroupsFree(htree_groups);
- return 0;
+ WebPSafeFree(huffman_tables_bogus);
+ WebPSafeFree(mapping);
+ if (!ok) {
+ WebPSafeFree(huffman_image);
+ WebPSafeFree(huffman_tables);
+ VP8LHtreeGroupsFree(htree_groups);
+ }
+ return ok;
}
//------------------------------------------------------------------------------
@@ -916,7 +933,11 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
#endif
break;
case 2:
+#if !defined(WORDS_BIGENDIAN)
memcpy(&pattern, src, sizeof(uint16_t));
+#else
+ pattern = ((uint32_t)src[0] << 8) | src[1];
+#endif
#if defined(__arm__) || defined(_M_ARM)
pattern |= pattern << 16;
#elif defined(WEBP_USE_MIPS_DSP_R2)
@@ -1555,7 +1576,6 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (dec == NULL) return 0;
assert(alph_dec != NULL);
- alph_dec->vp8l_dec_ = dec;
dec->width_ = alph_dec->width_;
dec->height_ = alph_dec->height_;
@@ -1587,11 +1607,12 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
if (!ok) goto Err;
+ // Only set here, once we are sure it is valid (to avoid thread races).
+ alph_dec->vp8l_dec_ = dec;
return 1;
Err:
- VP8LDelete(alph_dec->vp8l_dec_);
- alph_dec->vp8l_dec_ = NULL;
+ VP8LDelete(dec);
return 0;
}
diff --git a/media/libwebp/dec/vp8li_dec.h b/media/libwebp/dec/vp8li_dec.h
index ed89a02a9..2b9c95a44 100644
--- a/media/libwebp/dec/vp8li_dec.h
+++ b/media/libwebp/dec/vp8li_dec.h
@@ -132,4 +132,4 @@ void VP8LDelete(VP8LDecoder* const dec);
} // extern "C"
#endif
-#endif /* WEBP_DEC_VP8LI_DEC_H_ */
+#endif // WEBP_DEC_VP8LI_DEC_H_
diff --git a/media/libwebp/dec/webpi_dec.h b/media/libwebp/dec/webpi_dec.h
index d0a045e70..83d7444e5 100644
--- a/media/libwebp/dec/webpi_dec.h
+++ b/media/libwebp/dec/webpi_dec.h
@@ -130,4 +130,4 @@ int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
} // extern "C"
#endif
-#endif /* WEBP_DEC_WEBPI_DEC_H_ */
+#endif // WEBP_DEC_WEBPI_DEC_H_
diff --git a/media/libwebp/demux/demux.c b/media/libwebp/demux/demux.c
index aec2a0a2d..2034024d0 100644
--- a/media/libwebp/demux/demux.c
+++ b/media/libwebp/demux/demux.c
@@ -25,7 +25,7 @@
#define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 0
-#define DMUX_REV_VERSION 0
+#define DMUX_REV_VERSION 2
typedef struct {
size_t start_; // start location of the data
diff --git a/media/libwebp/dsp/dsp.h b/media/libwebp/dsp/dsp.h
index 537ea2044..4e509bd2c 100644
--- a/media/libwebp/dsp/dsp.h
+++ b/media/libwebp/dsp/dsp.h
@@ -76,10 +76,6 @@ extern "C" {
#define WEBP_USE_SSE41
#endif
-#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2)
-#define WEBP_USE_AVX2
-#endif
-
// The intrinsics currently cause compiler errors with arm-nacl-gcc and the
// inline assembly would need to be modified for use with Native Client.
#if (defined(__ARM_NEON__) || \
@@ -679,4 +675,4 @@ void VP8FiltersInit(void);
} // extern "C"
#endif
-#endif /* WEBP_DSP_DSP_H_ */
+#endif // WEBP_DSP_DSP_H_
diff --git a/media/libwebp/dsp/lossless.c b/media/libwebp/dsp/lossless.c
index 93ccecdfd..1a1523d22 100644
--- a/media/libwebp/dsp/lossless.c
+++ b/media/libwebp/dsp/lossless.c
@@ -23,8 +23,6 @@
#include "../dsp/lossless.h"
#include "../dsp/lossless_common.h"
-#define MAX_DIFF_COST (1e30f)
-
//------------------------------------------------------------------------------
// Image transforms.
diff --git a/media/libwebp/dsp/lossless.h b/media/libwebp/dsp/lossless.h
index 4a1d1e0dd..6db5fafc1 100644
--- a/media/libwebp/dsp/lossless.h
+++ b/media/libwebp/dsp/lossless.h
@@ -163,7 +163,7 @@ extern VP8LCostCombinedFunc VP8LExtraCostCombined;
extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
typedef struct { // small struct to hold counters
- int counts[2]; // index: 0=zero steak, 1=non-zero streak
+ int counts[2]; // index: 0=zero streak, 1=non-zero streak
int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3]
} VP8LStreaks;
@@ -194,10 +194,14 @@ extern VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;
void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n,
VP8LBitEntropy* const entropy);
-typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a,
- const VP8LHistogram* const b,
- VP8LHistogram* const out);
-extern VP8LHistogramAddFunc VP8LHistogramAdd;
+typedef void (*VP8LAddVectorFunc)(const uint32_t* a, const uint32_t* b,
+ uint32_t* out, int size);
+extern VP8LAddVectorFunc VP8LAddVector;
+typedef void (*VP8LAddVectorEqFunc)(const uint32_t* a, uint32_t* out, int size);
+extern VP8LAddVectorEqFunc VP8LAddVectorEq;
+void VP8LHistogramAdd(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ VP8LHistogram* const out);
// -----------------------------------------------------------------------------
// PrefixEncode()
diff --git a/media/libwebp/dsp/msa_macro.h b/media/libwebp/dsp/msa_macro.h
index dfacda6cc..de026a1d9 100644
--- a/media/libwebp/dsp/msa_macro.h
+++ b/media/libwebp/dsp/msa_macro.h
@@ -1389,4 +1389,4 @@ static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) {
} while (0)
#define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__)
-#endif /* WEBP_DSP_MSA_MACRO_H_ */
+#endif // WEBP_DSP_MSA_MACRO_H_
diff --git a/media/libwebp/dsp/quant.h b/media/libwebp/dsp/quant.h
new file mode 100644
index 000000000..b82e728a5
--- /dev/null
+++ b/media/libwebp/dsp/quant.h
@@ -0,0 +1,70 @@
+// Copyright 2018 Google Inc. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the COPYING file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS. All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+// -----------------------------------------------------------------------------
+
+#ifndef WEBP_DSP_QUANT_H_
+#define WEBP_DSP_QUANT_H_
+
+#include "../dsp/dsp.h"
+#include "../webp/types.h"
+
+#if defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && \
+ !defined(WEBP_HAVE_NEON_RTCD)
+#include <arm_neon.h>
+
+#define IsFlat IsFlat_NEON
+
+static uint32x2_t horizontal_add_uint32x4(const uint32x4_t a) {
+ const uint64x2_t b = vpaddlq_u32(a);
+ return vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
+ vreinterpret_u32_u64(vget_high_u64(b)));
+}
+
+static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
+ int thresh) {
+ const int16x8_t tst_ones = vdupq_n_s16(-1);
+ uint32x4_t sum = vdupq_n_u32(0);
+
+ for (int i = 0; i < num_blocks; ++i) {
+ // Set DC to zero.
+ const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0);
+ const int16x8_t a_1 = vld1q_s16(levels + 8);
+
+ const uint16x8_t b_0 = vshrq_n_u16(vtstq_s16(a_0, tst_ones), 15);
+ const uint16x8_t b_1 = vshrq_n_u16(vtstq_s16(a_1, tst_ones), 15);
+
+ sum = vpadalq_u16(sum, b_0);
+ sum = vpadalq_u16(sum, b_1);
+
+ levels += 16;
+ }
+ return thresh >= (int32_t)vget_lane_u32(horizontal_add_uint32x4(sum), 0);
+}
+
+#else
+
+#define IsFlat IsFlat_C
+
+static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
+ int thresh) {
+ int score = 0;
+ while (num_blocks-- > 0) { // TODO(skal): refine positional scoring?
+ int i;
+ for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC
+ score += (levels[i] != 0);
+ if (score > thresh) return 0;
+ }
+ levels += 16;
+ }
+ return 1;
+}
+
+#endif // defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) &&
+ // !defined(WEBP_HAVE_NEON_RTCD)
+
+#endif // WEBP_DSP_QUANT_H_
diff --git a/media/libwebp/dsp/rescaler.c b/media/libwebp/dsp/rescaler.c
index f70e6beef..6bf387f8e 100644
--- a/media/libwebp/dsp/rescaler.c
+++ b/media/libwebp/dsp/rescaler.c
@@ -21,6 +21,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
//------------------------------------------------------------------------------
// Row import
@@ -138,7 +139,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
if (yscale) {
for (x_out = 0; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -153,6 +154,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER
diff --git a/media/libwebp/dsp/rescaler_neon.c b/media/libwebp/dsp/rescaler_neon.c
index 835e646c1..b560d0cdc 100644
--- a/media/libwebp/dsp/rescaler_neon.c
+++ b/media/libwebp/dsp/rescaler_neon.c
@@ -22,6 +22,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR_C(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC))
#define LOAD_32x8(SRC, DST0, DST1) \
@@ -35,8 +36,11 @@
#if (WEBP_RESCALER_RFIX == 32)
#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1))
-#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \
+// note: B is actualy scale>>1. See MAKE_HALF_CST
+#define MULT_FIX(A, B) \
vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
+#define MULT_FIX_FLOOR(A, B) \
+ vreinterpretq_u32_s32(vqdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
#else
#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work"
#endif
@@ -135,8 +139,8 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
const uint32x4_t B0 = vqsubq_u32(in2, A0);
const uint32x4_t B1 = vqsubq_u32(in3, A1);
- const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half);
- const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half);
+ const uint32x4_t C0 = MULT_FIX_FLOOR(B0, fxy_scale_half);
+ const uint32x4_t C1 = MULT_FIX_FLOOR(B1, fxy_scale_half);
const uint16x4_t D0 = vmovn_u32(C0);
const uint16x4_t D1 = vmovn_u32(C1);
const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
@@ -145,7 +149,7 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
- const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR_C(irow[x_out] - frac, fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -170,6 +174,12 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR_C
+#undef MULT_FIX_C
+#undef MULT_FIX_FLOOR
+#undef MULT_FIX
+#undef ROUNDER
+
//------------------------------------------------------------------------------
extern void WebPRescalerDspInitNEON(void);
diff --git a/media/libwebp/dsp/rescaler_sse2.c b/media/libwebp/dsp/rescaler_sse2.c
index 1306f8457..2d35f76ab 100644
--- a/media/libwebp/dsp/rescaler_sse2.c
+++ b/media/libwebp/dsp/rescaler_sse2.c
@@ -25,6 +25,7 @@
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0
static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) {
@@ -224,6 +225,35 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0,
_mm_storel_epi64((__m128i*)dst, G);
}
+static WEBP_INLINE void ProcessRow_Floor_SSE2(const __m128i* const A0,
+ const __m128i* const A1,
+ const __m128i* const A2,
+ const __m128i* const A3,
+ const __m128i* const mult,
+ uint8_t* const dst) {
+ const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
+ const __m128i B0 = _mm_mul_epu32(*A0, *mult);
+ const __m128i B1 = _mm_mul_epu32(*A1, *mult);
+ const __m128i B2 = _mm_mul_epu32(*A2, *mult);
+ const __m128i B3 = _mm_mul_epu32(*A3, *mult);
+ const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX);
+ const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
+#if (WEBP_RESCALER_RFIX < 32)
+ const __m128i D2 =
+ _mm_and_si128(_mm_slli_epi64(B2, 32 - WEBP_RESCALER_RFIX), mask);
+ const __m128i D3 =
+ _mm_and_si128(_mm_slli_epi64(B3, 32 - WEBP_RESCALER_RFIX), mask);
+#else
+ const __m128i D2 = _mm_and_si128(B2, mask);
+ const __m128i D3 = _mm_and_si128(B3, mask);
+#endif
+ const __m128i E0 = _mm_or_si128(D0, D2);
+ const __m128i E1 = _mm_or_si128(D1, D3);
+ const __m128i F = _mm_packs_epi32(E0, E1);
+ const __m128i G = _mm_packus_epi16(F, F);
+ _mm_storel_epi64((__m128i*)dst, G);
+}
+
static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
int x_out;
uint8_t* const dst = wrk->dst;
@@ -322,12 +352,12 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
const __m128i G1 = _mm_or_si128(D1, F3);
_mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
_mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
- ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
+ ProcessRow_Floor_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
}
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
- const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
+ const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -352,6 +382,7 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
}
}
+#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER
diff --git a/media/libwebp/dsp/yuv.h b/media/libwebp/dsp/yuv.h
index b4c5d0b6c..947b89e13 100644
--- a/media/libwebp/dsp/yuv.h
+++ b/media/libwebp/dsp/yuv.h
@@ -207,4 +207,4 @@ static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) {
} // extern "C"
#endif
-#endif /* WEBP_DSP_YUV_H_ */
+#endif // WEBP_DSP_YUV_H_
diff --git a/media/libwebp/enc/cost_enc.h b/media/libwebp/enc/cost_enc.h
index d731ee2fa..114823234 100644
--- a/media/libwebp/enc/cost_enc.h
+++ b/media/libwebp/enc/cost_enc.h
@@ -79,4 +79,4 @@ extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES];
} // extern "C"
#endif
-#endif /* WEBP_ENC_COST_ENC_H_ */
+#endif // WEBP_ENC_COST_ENC_H_
diff --git a/media/libwebp/enc/histogram_enc.h b/media/libwebp/enc/histogram_enc.h
index 4fbb73702..ef39b7c6d 100644
--- a/media/libwebp/enc/histogram_enc.h
+++ b/media/libwebp/enc/histogram_enc.h
@@ -44,6 +44,7 @@ typedef struct {
double literal_cost_; // Cached values of dominant entropy costs:
double red_cost_; // literal, red & blue.
double blue_cost_;
+ uint8_t is_used_[5]; // 5 for literal, red, blue, alpha, distance
} VP8LHistogram;
// Collection of histograms with fixed capacity, allocated as one
@@ -67,7 +68,9 @@ void VP8LHistogramCreate(VP8LHistogram* const p,
int VP8LGetHistogramSize(int palette_code_bits);
// Set the palette_code_bits and reset the stats.
-void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits);
+// If init_arrays is true, the arrays are also filled with 0's.
+void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits,
+ int init_arrays);
// Collect all the references into a histogram (without reset)
void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
@@ -83,6 +86,9 @@ void VP8LFreeHistogramSet(VP8LHistogramSet* const histo);
// using 'cache_bits'. Return NULL in case of memory error.
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits);
+// Set the histograms in set to 0.
+void VP8LHistogramSetClear(VP8LHistogramSet* const set);
+
// Allocate and initialize histogram object with specified 'cache_bits'.
// Returns NULL in case of memory error.
// Special case of VP8LAllocateHistogramSet, with size equals 1.
@@ -113,7 +119,7 @@ double VP8LBitsEntropy(const uint32_t* const array, int n);
// Estimate how many bits the combined entropy of literals and distance
// approximately maps to.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
+double VP8LHistogramEstimateBits(VP8LHistogram* const p);
#ifdef __cplusplus
}
diff --git a/media/libwebp/enc/vp8i_enc.h b/media/libwebp/enc/vp8i_enc.h
index 8972d9f10..009ccf223 100644
--- a/media/libwebp/enc/vp8i_enc.h
+++ b/media/libwebp/enc/vp8i_enc.h
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 1
#define ENC_MIN_VERSION 0
-#define ENC_REV_VERSION 0
+#define ENC_REV_VERSION 2
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
@@ -278,7 +278,7 @@ int VP8IteratorIsDone(const VP8EncIterator* const it);
// Import uncompressed samples from source.
// If tmp_32 is not NULL, import boundary samples too.
// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory.
-void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32);
+void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32);
// export decimated samples
void VP8IteratorExport(const VP8EncIterator* const it);
// go to next macroblock. Returns false if not finished.
@@ -515,4 +515,4 @@ void WebPCleanupTransparentAreaLossless(WebPPicture* const pic);
} // extern "C"
#endif
-#endif /* WEBP_ENC_VP8I_ENC_H_ */
+#endif // WEBP_ENC_VP8I_ENC_H_
diff --git a/media/libwebp/enc/vp8li_enc.h b/media/libwebp/enc/vp8li_enc.h
index 5dcba9ef0..1e259eda7 100644
--- a/media/libwebp/enc/vp8li_enc.h
+++ b/media/libwebp/enc/vp8li_enc.h
@@ -115,4 +115,4 @@ void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
} // extern "C"
#endif
-#endif /* WEBP_ENC_VP8LI_ENC_H_ */
+#endif // WEBP_ENC_VP8LI_ENC_H_
diff --git a/media/libwebp/utils/bit_reader_inl_utils.h b/media/libwebp/utils/bit_reader_inl_utils.h
index 2bb9a1918..8d1249ef9 100644
--- a/media/libwebp/utils/bit_reader_inl_utils.h
+++ b/media/libwebp/utils/bit_reader_inl_utils.h
@@ -187,4 +187,4 @@ static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
} // extern "C"
#endif
-#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_
+#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_
diff --git a/media/libwebp/utils/bit_reader_utils.h b/media/libwebp/utils/bit_reader_utils.h
index 53e9db6ad..377a7821a 100644
--- a/media/libwebp/utils/bit_reader_utils.h
+++ b/media/libwebp/utils/bit_reader_utils.h
@@ -172,4 +172,4 @@ static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {
} // extern "C"
#endif
-#endif /* WEBP_UTILS_BIT_READER_UTILS_H_ */
+#endif // WEBP_UTILS_BIT_READER_UTILS_H_
diff --git a/media/libwebp/utils/bit_writer_utils.h b/media/libwebp/utils/bit_writer_utils.h
index 9e9c2b729..b854fae73 100644
--- a/media/libwebp/utils/bit_writer_utils.h
+++ b/media/libwebp/utils/bit_writer_utils.h
@@ -151,4 +151,4 @@ static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_BIT_WRITER_UTILS_H_ */
+#endif // WEBP_UTILS_BIT_WRITER_UTILS_H_
diff --git a/media/libwebp/utils/filters_utils.h b/media/libwebp/utils/filters_utils.h
index 9466030e5..891771ddc 100644
--- a/media/libwebp/utils/filters_utils.h
+++ b/media/libwebp/utils/filters_utils.h
@@ -29,4 +29,4 @@ WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_FILTERS_UTILS_H_ */
+#endif // WEBP_UTILS_FILTERS_UTILS_H_
diff --git a/media/libwebp/utils/quant_levels_dec_utils.c b/media/libwebp/utils/quant_levels_dec_utils.c
index 5c498382d..a60de3444 100644
--- a/media/libwebp/utils/quant_levels_dec_utils.c
+++ b/media/libwebp/utils/quant_levels_dec_utils.c
@@ -261,9 +261,15 @@ static void CleanupParams(SmoothParams* const p) {
int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
int strength) {
- const int radius = 4 * strength / 100;
+ int radius = 4 * strength / 100;
+
if (strength < 0 || strength > 100) return 0;
if (data == NULL || width <= 0 || height <= 0) return 0; // bad params
+
+ // limit the filter size to not exceed the image dimensions
+ if (2 * radius + 1 > width) radius = (width - 1) >> 1;
+ if (2 * radius + 1 > height) radius = (height - 1) >> 1;
+
if (radius > 0) {
SmoothParams p;
memset(&p, 0, sizeof(p));
diff --git a/media/libwebp/utils/quant_levels_dec_utils.h b/media/libwebp/utils/quant_levels_dec_utils.h
index 4a59e06fe..c05376c67 100644
--- a/media/libwebp/utils/quant_levels_dec_utils.h
+++ b/media/libwebp/utils/quant_levels_dec_utils.h
@@ -32,4 +32,4 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ */
+#endif // WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_
diff --git a/media/libwebp/utils/quant_levels_utils.h b/media/libwebp/utils/quant_levels_utils.h
index 837bd2730..52a25a5f9 100644
--- a/media/libwebp/utils/quant_levels_utils.h
+++ b/media/libwebp/utils/quant_levels_utils.h
@@ -33,4 +33,4 @@ int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_QUANT_LEVELS_UTILS_H_ */
+#endif // WEBP_UTILS_QUANT_LEVELS_UTILS_H_
diff --git a/media/libwebp/utils/random_utils.h b/media/libwebp/utils/random_utils.h
index 7b58de8c9..6688d2801 100644
--- a/media/libwebp/utils/random_utils.h
+++ b/media/libwebp/utils/random_utils.h
@@ -60,4 +60,4 @@ static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) {
} // extern "C"
#endif
-#endif /* WEBP_UTILS_RANDOM_UTILS_H_ */
+#endif // WEBP_UTILS_RANDOM_UTILS_H_
diff --git a/media/libwebp/utils/rescaler_utils.h b/media/libwebp/utils/rescaler_utils.h
index 1c7b31d7f..b5d176ecf 100644
--- a/media/libwebp/utils/rescaler_utils.h
+++ b/media/libwebp/utils/rescaler_utils.h
@@ -98,4 +98,4 @@ int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) {
} // extern "C"
#endif
-#endif /* WEBP_UTILS_RESCALER_UTILS_H_ */
+#endif // WEBP_UTILS_RESCALER_UTILS_H_
diff --git a/media/libwebp/utils/thread_utils.h b/media/libwebp/utils/thread_utils.h
index 0e88c2470..eb788f6e0 100644
--- a/media/libwebp/utils/thread_utils.h
+++ b/media/libwebp/utils/thread_utils.h
@@ -87,4 +87,4 @@ WEBP_EXTERN const WebPWorkerInterface* WebPGetWorkerInterface(void);
} // extern "C"
#endif
-#endif /* WEBP_UTILS_THREAD_UTILS_H_ */
+#endif // WEBP_UTILS_THREAD_UTILS_H_
diff --git a/media/libwebp/utils/utils.h b/media/libwebp/utils/utils.h
index 27dc7e090..d22151b0f 100644
--- a/media/libwebp/utils/utils.h
+++ b/media/libwebp/utils/utils.h
@@ -107,19 +107,6 @@ static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
PutLE16(data + 2, (int)(val >> 16));
}
-// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either
-// based on table or not. Can be used as fallback if clz() is not available.
-#define WEBP_NEED_LOG_TABLE_8BIT
-extern const uint8_t WebPLogTable8bit[256];
-static WEBP_INLINE int WebPLog2FloorC(uint32_t n) {
- int log_value = 0;
- while (n >= 256) {
- log_value += 8;
- n >>= 8;
- }
- return log_value + WebPLogTable8bit[n];
-}
-
// Returns (int)floor(log2(n)). n must be > 0.
// use GNU builtins where available.
#if defined(__GNUC__) && \
@@ -138,6 +125,19 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
return first_set_bit;
}
#else // default: use the C-version.
+// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either
+// based on table or not. Can be used as fallback if clz() is not available.
+#define WEBP_NEED_LOG_TABLE_8BIT
+extern const uint8_t WebPLogTable8bit[256];
+static WEBP_INLINE int WebPLog2FloorC(uint32_t n) {
+ int log_value = 0;
+ while (n >= 256) {
+ log_value += 8;
+ n >>= 8;
+ }
+ return log_value + WebPLogTable8bit[n];
+}
+
static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); }
#endif
@@ -175,4 +175,4 @@ WEBP_EXTERN int WebPGetColorPalette(const struct WebPPicture* const pic,
} // extern "C"
#endif
-#endif /* WEBP_UTILS_UTILS_H_ */
+#endif // WEBP_UTILS_UTILS_H_
diff --git a/media/libwebp/webp/decode.h b/media/libwebp/webp/decode.h
index 2165e96c9..ae8bfe840 100644
--- a/media/libwebp/webp/decode.h
+++ b/media/libwebp/webp/decode.h
@@ -42,6 +42,12 @@ WEBP_EXTERN int WebPGetDecoderVersion(void);
// This function will also validate the header, returning true on success,
// false otherwise. '*width' and '*height' are only valid on successful return.
// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant.
+// Note: The following chunk sequences (before the raw VP8/VP8L data) are
+// considered valid by this function:
+// RIFF + VP8(L)
+// RIFF + VP8X + (optional chunks) + VP8(L)
+// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
+// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size,
int* width, int* height);
@@ -425,6 +431,12 @@ WEBP_EXTERN VP8StatusCode WebPGetFeaturesInternal(
// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns
// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the
// features from headers. Returns error in other cases.
+// Note: The following chunk sequences (before the raw VP8/VP8L data) are
+// considered valid by this function:
+// RIFF + VP8(L)
+// RIFF + VP8X + (optional chunks) + VP8(L)
+// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
+// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
static WEBP_INLINE VP8StatusCode WebPGetFeatures(
const uint8_t* data, size_t data_size,
WebPBitstreamFeatures* features) {
@@ -491,4 +503,4 @@ WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
} // extern "C"
#endif
-#endif /* WEBP_WEBP_DECODE_H_ */
+#endif // WEBP_WEBP_DECODE_H_
diff --git a/media/libwebp/webp/demux.h b/media/libwebp/webp/demux.h
index 555d64133..846eeb15a 100644
--- a/media/libwebp/webp/demux.h
+++ b/media/libwebp/webp/demux.h
@@ -360,4 +360,4 @@ WEBP_EXTERN void WebPAnimDecoderDelete(WebPAnimDecoder* dec);
} // extern "C"
#endif
-#endif /* WEBP_WEBP_DEMUX_H_ */
+#endif // WEBP_WEBP_DEMUX_H_
diff --git a/media/libwebp/webp/encode.h b/media/libwebp/webp/encode.h
index 7ec3543dc..549cf0773 100644
--- a/media/libwebp/webp/encode.h
+++ b/media/libwebp/webp/encode.h
@@ -542,4 +542,4 @@ WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture);
} // extern "C"
#endif
-#endif /* WEBP_WEBP_ENCODE_H_ */
+#endif // WEBP_WEBP_ENCODE_H_
diff --git a/media/libwebp/webp/format_constants.h b/media/libwebp/webp/format_constants.h
index 329fc8a3b..eca6981a4 100644
--- a/media/libwebp/webp/format_constants.h
+++ b/media/libwebp/webp/format_constants.h
@@ -84,4 +84,4 @@ typedef enum {
// overflow a uint32_t.
#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1)
-#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */
+#endif // WEBP_WEBP_FORMAT_CONSTANTS_H_
diff --git a/media/libwebp/webp/mux.h b/media/libwebp/webp/mux.h
index 28bb4a41c..66096a92e 100644
--- a/media/libwebp/webp/mux.h
+++ b/media/libwebp/webp/mux.h
@@ -527,4 +527,4 @@ WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc);
} // extern "C"
#endif
-#endif /* WEBP_WEBP_MUX_H_ */
+#endif // WEBP_WEBP_MUX_H_
diff --git a/media/libwebp/webp/mux_types.h b/media/libwebp/webp/mux_types.h
index b37e2c67a..ceea77dfc 100644
--- a/media/libwebp/webp/mux_types.h
+++ b/media/libwebp/webp/mux_types.h
@@ -95,4 +95,4 @@ static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
} // extern "C"
#endif
-#endif /* WEBP_WEBP_MUX_TYPES_H_ */
+#endif // WEBP_WEBP_MUX_TYPES_H_
diff --git a/media/libwebp/webp/types.h b/media/libwebp/webp/types.h
index 989a763f0..0ce2622e4 100644
--- a/media/libwebp/webp/types.h
+++ b/media/libwebp/webp/types.h
@@ -49,4 +49,4 @@ typedef long long int int64_t;
// Macro to check ABI compatibility (same major revision number)
#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))
-#endif /* WEBP_WEBP_TYPES_H_ */
+#endif // WEBP_WEBP_TYPES_H_
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 21e36bf16..3e1dc47ef 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -213,7 +213,7 @@ pref("dom.requestIdleCallback.enabled", true);
// Enable Intersection Observers
// See WD https://www.w3.org/TR/intersection-observer/
-pref("dom.IntersectionObserver.enabled", true);
+pref("dom.intersectionObserver.enabled", true);
// Whether the Gamepad API is enabled
pref("dom.gamepad.enabled", true);
diff --git a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
index 6c470356a..59d84ced1 100644
--- a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
+++ b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
@@ -1082,6 +1082,9 @@ nsPerformanceStatsService::GetPerformanceGroups(JSContext* cx,
return false;
}
+ // Returning a vector that is too large would cause allocations all over the
+ // place in the JS engine. We want to be sure that all data is stored inline.
+ MOZ_ASSERT(out.length() <= out.sMaxInlineStorage);
return true;
}
@@ -1310,8 +1313,12 @@ nsPerformanceStatsService::GetResources(uint64_t* userTime,
void
nsPerformanceStatsService::NotifyJankObservers(const mozilla::Vector<uint64_t>& aPreviousJankLevels) {
- GroupVector alerts;
- mPendingAlerts.swap(alerts);
+
+ // The move operation is generally constant time, unless
+ // `mPendingAlerts.length()` is very small, in which case it's fast anyway.
+ GroupVector alerts(Move(mPendingAlerts));
+ mPendingAlerts = GroupVector(); // Reconstruct after `Move`.
+
if (!mPendingAlertsCollector) {
// We are shutting down.
return;
diff --git a/toolkit/components/perfmonitoring/nsPerformanceStats.h b/toolkit/components/perfmonitoring/nsPerformanceStats.h
index 6902c840d..661a78a1a 100644
--- a/toolkit/components/perfmonitoring/nsPerformanceStats.h
+++ b/toolkit/components/perfmonitoring/nsPerformanceStats.h
@@ -19,7 +19,7 @@
class nsPerformanceGroup;
class nsPerformanceGroupDetails;
-typedef mozilla::Vector<RefPtr<nsPerformanceGroup>> GroupVector;
+typedef mozilla::Vector<RefPtr<nsPerformanceGroup>, 8> GroupVector;
/**
* A data structure for registering observers interested in
diff --git a/toolkit/mozapps/extensions/content/extensions.xml b/toolkit/mozapps/extensions/content/extensions.xml
index cbd05bfa9..9c8fda8ed 100644
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ b/toolkit/mozapps/extensions/content/extensions.xml
@@ -941,10 +941,6 @@
#endif
oncommand="document.getBindingParent(this).showPreferences();"/>
<!-- label="&cmd.debugAddon.label;" -->
- <xul:button anonid="debug-btn" class="addon-control debug"
- label="&cmd.debugAddon.label;"
- oncommand="document.getBindingParent(this).debug();"/>
-
<xul:button anonid="enable-btn" class="addon-control enable"
label="&cmd.enableAddon.label;"
oncommand="document.getBindingParent(this).userDisabled = false;"/>
@@ -1087,10 +1083,6 @@
document.getAnonymousElementByAttribute(this, "anonid",
"enable-btn");
</field>
- <field name="_debugBtn">
- document.getAnonymousElementByAttribute(this, "anonid",
- "debug-btn");
- </field>
<field name="_disableBtn">
document.getAnonymousElementByAttribute(this, "anonid",
"disable-btn");
@@ -1430,12 +1422,6 @@
this.mAddon.install.state != AddonManager.STATE_INSTALLED);
this._showStatus(showProgress ? "progress" : "none");
- let debuggable = this.mAddon.isDebuggable &&
- Services.prefs.getBoolPref('devtools.chrome.enabled') &&
- Services.prefs.getBoolPref('devtools.debugger.remote-enabled');
-
- this._debugBtn.disabled = this._debugBtn.hidden = !debuggable
-
if (this.mAddon.type == "experiment") {
this.removeAttribute("notification");
let prefix = "experiment.";