Merge m-c to fx-team, a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 05 Aug 2016 14:06:23 -0700
changeset 308381 ba6d10b9a178a5700620a48b77b152908d4f8781
parent 308345 f54fea6078ddf0023a4307a25264c6ece653e503 (current diff)
parent 308380 6b65dd49d4f045c0a9753ce60bdb4b7b4aaedcf8 (diff)
child 308382 1646172ac6e709f5abdecbd8edbb53a54392428a
push id20240
push userkwierso@gmail.com
push dateFri, 05 Aug 2016 21:06:31 +0000
treeherderfx-team@ba6d10b9a178 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone51.0a1
Merge m-c to fx-team, a=merge
.eslintignore
media/ffvpx/libavcodec/avdct.c
media/ffvpx/libavcodec/bsf.c
media/ffvpx/libavcodec/options_table.h
media/ffvpx/libavutil/opt.c
modules/libpref/init/all.js
testing/mozharness/test/helper_files/archives/archive.tar
testing/mozharness/test/helper_files/archives/archive.tar.bz2
testing/mozharness/test/helper_files/archives/archive.tar.gz
testing/mozharness/test/helper_files/archives/archive.zip
testing/mozharness/test/helper_files/archives/archive_invalid_filename.zip
testing/mozharness/test/helper_files/archives/reference/bin/script.sh
testing/mozharness/test/helper_files/archives/reference/lorem.txt
testing/mozharness/test/helper_files/create_archives.sh
testing/web-platform/meta/XMLHttpRequest/send-accept.htm.ini
testing/web-platform/meta/html/semantics/forms/textfieldselection/selection.html.ini
--- a/.eslintignore
+++ b/.eslintignore
@@ -121,19 +121,21 @@ devtools/server/actors/**
 !devtools/server/actors/webbrowser.js
 !devtools/server/actors/webextension.js
 !devtools/server/actors/styles.js
 !devtools/server/actors/string.js
 !devtools/server/actors/csscoverage.js
 devtools/server/performance/**
 devtools/server/tests/**
 devtools/shared/*.js
+!devtools/shared/async-utils.js
 !devtools/shared/css-lexer.js
 !devtools/shared/defer.js
 !devtools/shared/event-emitter.js
+!devtools/shared/indentation.js
 !devtools/shared/loader-plugin-raw.jsm
 !devtools/shared/task.js
 devtools/shared/*.jsm
 !devtools/shared/Loader.jsm
 devtools/shared/apps/**
 devtools/shared/client/**
 devtools/shared/discovery/**
 devtools/shared/gcli/**
--- a/accessible/tests/mochitest/jsat/test_content_text.html
+++ b/accessible/tests/mochitest/jsat/test_content_text.html
@@ -63,26 +63,26 @@
              { android_todo: true /* Bug 980512 */})],
 
           // Editable text tests.
           [ContentMessages.focusSelector('textarea'),
            new ExpectedAnnouncement('editing'),
            new ExpectedEditState({
             editing: true,
             multiline: true,
-            atStart: true,
-            atEnd: false
+            atStart: false,
+            atEnd: true
            }),
            new ExpectedCursorChange(
             ['Please refrain from Mayoneggs during this salmonella scare.',
              {string: 'textarea'}]),
-           new ExpectedTextSelectionChanged(0, 0)
+           new ExpectedTextSelectionChanged(59, 59)
           ],
           [ContentMessages.activateCurrent(10),
-           new ExpectedTextCaretChanged(0, 10),
+           new ExpectedTextCaretChanged(10, 59),
            new ExpectedEditState({ editing: true,
              multiline: true,
              atStart: false,
              atEnd: false }),
            new ExpectedTextSelectionChanged(10, 10)],
           [ContentMessages.activateCurrent(20),
            new ExpectedTextCaretChanged(10, 20),
            new ExpectedTextSelectionChanged(20, 20)
@@ -131,28 +131,30 @@
            new ExpectedClickAction(),
            new ExpectedAnnouncement('editing'),
            new ExpectedEditState({
             editing: true,
             multiline: false,
             atStart: true,
             atEnd: true
            }, { focused: 'input[type=text]' }),
+           new ExpectedTextSelectionChanged(0, 0),
            new ExpectedTextSelectionChanged(0, 0)
            ],
           [ContentMessages.simpleMovePrevious,
            new ExpectedCursorChange(
             ['So we don\'t get dessert?', {string: 'label'}]),
            new ExpectedAnnouncement('navigating'),
            new ExpectedEditState({
             editing: false,
             multiline: false,
             atStart: true,
             atEnd: false
-           }, { focused: 'html' })],
+           },{ focused: 'html' })
+         ],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(
             [{ string : 'entry' }],
             { focused: 'html'})],
           [ContentMessages.activateCurrent(0),
            new ExpectedClickAction(),
            new ExpectedAnnouncement('editing'),
            new ExpectedEditState({
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1345,18 +1345,27 @@ pref("media.gmp.trial-create.enabled", t
 
 #ifdef MOZ_ADOBE_EME
 pref("media.gmp-eme-adobe.visible", true);
 pref("media.gmp-eme-adobe.enabled", true);
 #endif
 
 #ifdef MOZ_WIDEVINE_EME
 pref("media.gmp-widevinecdm.visible", true);
+// On Linux Widevine is visible but disabled by default. This is because
+// enabling Widevine downloads a proprietary binary, which users on an open
+// source operating system didn't opt into. The first time a site using EME
+// is encountered, the user will be prompted to enable EME, whereupon the
+// EME plugin binary will be downloaded if permission is granted.
+#ifdef XP_LINUX
+pref("media.gmp-widevinecdm.enabled", false);
+#else
 pref("media.gmp-widevinecdm.enabled", true);
 #endif
+#endif
 
 // Play with different values of the decay time and get telemetry,
 // 0 means to randomize (and persist) the experiment value in users' profiles,
 // -1 means no experiment is run and we use the preferred value for frecency (6h)
 pref("browser.cache.frecency_experiment", 0);
 
 pref("browser.translation.detectLanguage", false);
 pref("browser.translation.neverForLanguages", "");
--- a/browser/config/mozconfigs/macosx-universal/common-opt
+++ b/browser/config/mozconfigs/macosx-universal/common-opt
@@ -13,15 +13,10 @@ ac_add_options --with-mozilla-api-keyfil
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
-# Enable Widevine CDMs on MacOSX in Mozilla builds.
-# Enabled here on the assumption that downstream vendors will not be using
-# these build configs.
-ac_add_options --enable-eme=widevine
-
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win32/common-opt
+++ b/browser/config/mozconfigs/win32/common-opt
@@ -26,15 +26,17 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 . $topsrcdir/build/win32/mozconfig.vs-latest
 
 # Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
-# Enable Adobe Primetime and Widevine CDMs on 32-bit Windows in Mozilla builds.
+# Enable Adobe Primetime CDM on 32-bit Windows in Mozilla builds.
 # Enabled here on the assumption that downstream vendors will not be using
 # these build configs.
-ac_add_options --enable-eme=adobe,widevine
+# Note: Widevine is automatically enabled by the build, and can be
+# disabled with -widevine.
+ac_add_options --enable-eme=+adobe
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/win64/common-opt
+++ b/browser/config/mozconfigs/win64/common-opt
@@ -24,15 +24,17 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
 ac_add_options --enable-warnings-as-errors
 
 . $topsrcdir/build/win64/mozconfig.vs-latest
 
-# Enable Adobe Primetime and Widevine CDMs on 64-bit Windows in Mozilla builds.
+# Enable Adobe Primetime CDM on 64-bit Windows in Mozilla builds.
 # Enabled here on the assumption that downstream vendors will not be using
 # these build configs.
-ac_add_options --enable-eme=adobe,widevine
+# Note: Widevine is automatically enabled by the build, and can be
+# disabled with -widevine.
+ac_add_options --enable-eme=+adobe
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
--- a/devtools/client/inspector/breadcrumbs.js
+++ b/devtools/client/inspector/breadcrumbs.js
@@ -17,20 +17,18 @@ const {waitForTick} = require("devtools/
 const ELLIPSIS = Services.prefs.getComplexValue(
     "intl.ellipsis",
     Ci.nsIPrefLocalizedString).data;
 const MAX_LABEL_LENGTH = 40;
 
 const NS_XHTML = "http://www.w3.org/1999/xhtml";
 const SCROLL_REPEAT_MS = 100;
 
-loader.lazyRequireGetter(this, "EventEmitter",
-                         "devtools/shared/event-emitter");
-loader.lazyRequireGetter(this, "KeyShortcuts",
-                         "devtools/client/shared/key-shortcuts", true);
+const EventEmitter = require("devtools/shared/event-emitter");
+const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
 
 /**
  * Component to replicate functionality of XUL arrowscrollbox
  * for breadcrumbs
  *
  * @param {Window} win The window containing the breadcrumbs
  * @parem {DOMNode} container The element in which to put the scroll box
  */
--- a/devtools/client/inspector/computed/computed.js
+++ b/devtools/client/inspector/computed/computed.js
@@ -22,24 +22,20 @@ const {OutputParser} = require("devtools
 const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 const {createChild} = require("devtools/client/inspector/shared/utils");
 const {gDevTools} = require("devtools/client/framework/devtools");
 /* eslint-disable mozilla/reject-some-requires */
 const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
 /* eslint-enable mozilla/reject-some-requires */
 const {getCssProperties} = require("devtools/shared/fronts/css-properties");
 
-loader.lazyRequireGetter(this, "overlays",
-  "devtools/client/inspector/shared/style-inspector-overlays");
-loader.lazyRequireGetter(this, "StyleInspectorMenu",
-  "devtools/client/inspector/shared/style-inspector-menu");
-loader.lazyRequireGetter(this, "KeyShortcuts",
-  "devtools/client/shared/key-shortcuts", true);
-loader.lazyRequireGetter(this, "LayoutView",
-  "devtools/client/inspector/layout/layout", true);
+const overlays = require("devtools/client/inspector/shared/style-inspector-overlays");
+const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
+const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
+const {LayoutView} = require("devtools/client/inspector/layout/layout");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
                                   "resource://gre/modules/PluralForm.jsm");
 
 XPCOMUtils.defineLazyGetter(CssComputedView, "_strings", function () {
   return Services.strings.createBundle(
     "chrome://devtools-shared/locale/styleinspector.properties");
 });
--- a/devtools/client/inspector/inspector-commands.js
+++ b/devtools/client/inspector/inspector-commands.js
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const l10n = require("gcli/l10n");
-loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
+const {gDevTools} = require("devtools/client/framework/devtools");
 /* eslint-disable mozilla/reject-some-requires */
 const {EyeDropper, HighlighterEnvironment} = require("devtools/server/actors/highlighters");
 /* eslint-enable mozilla/reject-some-requires */
 const Telemetry = require("devtools/client/shared/telemetry");
 
 exports.items = [{
   item: "command",
   runAt: "client",
--- a/devtools/client/inspector/inspector-panel.js
+++ b/devtools/client/inspector/inspector-panel.js
@@ -1,15 +1,13 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/* Experimenting with 100 char long lines */
-/* eslint max-len: [2, 100, 2, {ignoreUrls: true, "ignorePattern": "\\s*require\\s*\\(|^\\s*loader\\.lazy|-\\*-"}] */ // eslint-disable-line
 
 "use strict";
 
 /* eslint-disable mozilla/reject-some-requires */
 const {Cc, Ci} = require("chrome");
 /* eslint-enable mozilla/reject-some-requires */
 
 var Services = require("Services");
@@ -22,27 +20,27 @@ var {KeyShortcuts} = require("devtools/c
 var {Task} = require("devtools/shared/task");
 const {initCssProperties} = require("devtools/shared/fronts/css-properties");
 const nodeConstants = require("devtools/shared/dom-node-constants");
 const Telemetry = require("devtools/client/shared/telemetry");
 
 const Menu = require("devtools/client/framework/menu");
 const MenuItem = require("devtools/client/framework/menu-item");
 
-loader.lazyRequireGetter(this, "CSS", "CSS");
+const CSS = require("CSS");
 
-loader.lazyRequireGetter(this, "CommandUtils", "devtools/client/shared/developer-toolbar", true);
-loader.lazyRequireGetter(this, "ComputedViewTool", "devtools/client/inspector/computed/computed", true);
-loader.lazyRequireGetter(this, "FontInspector", "devtools/client/inspector/fonts/fonts", true);
-loader.lazyRequireGetter(this, "HTMLBreadcrumbs", "devtools/client/inspector/breadcrumbs", true);
-loader.lazyRequireGetter(this, "InspectorSearch", "devtools/client/inspector/inspector-search", true);
-loader.lazyRequireGetter(this, "MarkupView", "devtools/client/inspector/markup/markup", true);
-loader.lazyRequireGetter(this, "RuleViewTool", "devtools/client/inspector/rules/rules", true);
-loader.lazyRequireGetter(this, "ToolSidebar", "devtools/client/inspector/toolsidebar", true);
-loader.lazyRequireGetter(this, "ViewHelpers", "devtools/client/shared/widgets/view-helpers", true);
+const {CommandUtils} = require("devtools/client/shared/developer-toolbar");
+const {ComputedViewTool} = require("devtools/client/inspector/computed/computed");
+const {FontInspector} = require("devtools/client/inspector/fonts/fonts");
+const {HTMLBreadcrumbs} = require("devtools/client/inspector/breadcrumbs");
+const {InspectorSearch} = require("devtools/client/inspector/inspector-search");
+const {MarkupView} = require("devtools/client/inspector/markup/markup");
+const {RuleViewTool} = require("devtools/client/inspector/rules/rules");
+const {ToolSidebar} = require("devtools/client/inspector/toolsidebar");
+const {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
 
 loader.lazyGetter(this, "strings", () => {
   return Services.strings.createBundle("chrome://devtools/locale/inspector.properties");
 });
 loader.lazyGetter(this, "toolboxStrings", () => {
   return Services.strings.createBundle("chrome://devtools/locale/toolbox.properties");
 });
 loader.lazyGetter(this, "clipboardHelper", () => {
@@ -211,17 +209,18 @@ InspectorPanel.prototype = {
     this.breadcrumbs = new HTMLBreadcrumbs(this);
 
     if (this.target.isLocalTab) {
       // Show a warning when the debugger is paused.
       // We show the warning only when the inspector
       // is selected.
       this.updateDebuggerPausedWarning = () => {
         let notificationBox = this._toolbox.getNotificationBox();
-        let notification = notificationBox.getNotificationWithValue("inspector-script-paused");
+        let notification =
+            notificationBox.getNotificationWithValue("inspector-script-paused");
         if (!notification && this._toolbox.currentToolId == "inspector" &&
             this._toolbox.threadClient.paused) {
           let message = strings.GetStringFromName("debuggerPausedWarning.message");
           notificationBox.appendNotification(message,
             "inspector-script-paused", "", notificationBox.PRIORITY_WARNING_HIGH);
         }
 
         if (notification && this._toolbox.currentToolId != "inspector") {
@@ -1512,29 +1511,33 @@ InspectorPanel.prototype = {
   copyImageDataUri: function () {
     let container = this.markup.getContainer(this.selection.nodeFront);
     if (container && container.isPreviewable()) {
       container.copyImageDataUri();
     }
   },
 
   /**
-   * Copy the content of a longString (via a promise resolving a LongStringActor) to the clipboard
-   * @param  {Promise} longStringActorPromise promise expected to resolve a LongStringActor instance
-   * @return {Promise} promise resolving (with no argument) when the string is sent to the clipboard
+   * Copy the content of a longString (via a promise resolving a
+   * LongStringActor) to the clipboard
+   * @param  {Promise} longStringActorPromise promise expected to
+   *         resolve a LongStringActor instance
+   * @return {Promise} promise resolving (with no argument) when the
+   *         string is sent to the clipboard
    */
   _copyLongString: function (longStringActorPromise) {
     return this._getLongString(longStringActorPromise).then(string => {
       clipboardHelper.copyString(string);
     }).catch(e => console.error(e));
   },
 
   /**
    * Retrieve the content of a longString (via a promise resolving a LongStringActor)
-   * @param  {Promise} longStringActorPromise promise expected to resolve a LongStringActor instance
+   * @param  {Promise} longStringActorPromise promise expected to
+   *         resolve a LongStringActor instance
    * @return {Promise} promise resolving with the retrieved string as argument
    */
   _getLongString: function (longStringActorPromise) {
     return longStringActorPromise.then(longStringActor => {
       return longStringActor.string().then(string => {
         longStringActor.release().catch(e => console.error(e));
         return string;
       });
--- a/devtools/client/inspector/inspector-search.js
+++ b/devtools/client/inspector/inspector-search.js
@@ -5,19 +5,19 @@
 "use strict";
 
 /* eslint-disable mozilla/reject-some-requires */
 const {Ci} = require("chrome");
 /* eslint-enable mozilla/reject-some-requires */
 const promise = require("promise");
 const {Task} = require("devtools/shared/task");
 
-loader.lazyGetter(this, "system", () => require("devtools/shared/system"));
-loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter"));
-loader.lazyGetter(this, "AutocompletePopup", () => require("devtools/client/shared/autocomplete-popup").AutocompletePopup);
+const system = require("devtools/shared/system");
+const EventEmitter = require("devtools/shared/event-emitter");
+const {AutocompletePopup} = require("devtools/client/shared/autocomplete-popup");
 
 // Maximum number of selector suggestions shown in the panel.
 const MAX_SUGGESTIONS = 15;
 
 /**
  * Converts any input field into a document search box.
  *
  * @param {InspectorPanel} inspector The InspectorPanel whose `walker` attribute
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -56,20 +56,18 @@ const {KeyShortcuts} = require("devtools
 const {template} = require("devtools/shared/gcli/templater");
 const nodeConstants = require("devtools/shared/dom-node-constants");
 const nodeFilterConstants = require("devtools/shared/dom-node-filter-constants");
 /* eslint-disable mozilla/reject-some-requires */
 const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
 /* eslint-enable mozilla/reject-some-requires */
 const {getCssProperties} = require("devtools/shared/fronts/css-properties");
 
-loader.lazyRequireGetter(this, "CSS", "CSS");
-loader.lazyGetter(this, "AutocompletePopup", () => {
-  return require("devtools/client/shared/autocomplete-popup").AutocompletePopup;
-});
+const CSS = require("CSS");
+const {AutocompletePopup} = require("devtools/client/shared/autocomplete-popup");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
   "resource://gre/modules/PluralForm.jsm");
 
 /**
  * Vocabulary for the purposes of this file:
  *
  * MarkupContainer - the structure that holds an editor and its
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -24,38 +24,32 @@ const {OutputParser} = require("devtools
 const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 const {ElementStyle} = require("devtools/client/inspector/rules/models/element-style");
 const {Rule} = require("devtools/client/inspector/rules/models/rule");
 const {RuleEditor} = require("devtools/client/inspector/rules/views/rule-editor");
 const {createChild, promiseWarn, throttle} = require("devtools/client/inspector/shared/utils");
 const {gDevTools} = require("devtools/client/framework/devtools");
 const {getCssProperties} = require("devtools/shared/fronts/css-properties");
 
-loader.lazyRequireGetter(this, "overlays",
-  "devtools/client/inspector/shared/style-inspector-overlays");
-loader.lazyRequireGetter(this, "EventEmitter",
-  "devtools/shared/event-emitter");
-loader.lazyRequireGetter(this, "StyleInspectorMenu",
-  "devtools/client/inspector/shared/style-inspector-menu");
-loader.lazyRequireGetter(this, "KeyShortcuts",
-  "devtools/client/shared/key-shortcuts", true);
+const overlays = require("devtools/client/inspector/shared/style-inspector-overlays");
+const EventEmitter = require("devtools/shared/event-emitter");
+const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
+const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
 
 XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function () {
   return Cc["@mozilla.org/widget/clipboardhelper;1"]
     .getService(Ci.nsIClipboardHelper);
 });
 
 XPCOMUtils.defineLazyGetter(this, "_strings", function () {
   return Services.strings.createBundle(
     "chrome://devtools-shared/locale/styleinspector.properties");
 });
 
-loader.lazyGetter(this, "AutocompletePopup", function () {
-  return require("devtools/client/shared/autocomplete-popup").AutocompletePopup;
-});
+const {AutocompletePopup} = require("devtools/client/shared/autocomplete-popup");
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const PREF_UA_STYLES = "devtools.inspector.showUserAgentStyles";
 const PREF_DEFAULT_COLOR_UNIT = "devtools.defaultColorUnit";
 const PREF_ENABLE_MDN_DOCS_TOOLTIP =
       "devtools.inspector.mdnDocsTooltip.enabled";
 const FILTER_CHANGED_TIMEOUT = 150;
 
--- a/devtools/client/inspector/shared/style-inspector-menu.js
+++ b/devtools/client/inspector/shared/style-inspector-menu.js
@@ -9,18 +9,17 @@
 
 const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 const Services = require("Services");
 const {Task} = require("devtools/shared/task");
 
 const Menu = require("devtools/client/framework/menu");
 const MenuItem = require("devtools/client/framework/menu-item");
 
-loader.lazyRequireGetter(this, "overlays",
-  "devtools/client/inspector/shared/style-inspector-overlays");
+const overlays = require("devtools/client/inspector/shared/style-inspector-overlays");
 loader.lazyServiceGetter(this, "clipboardHelper",
   "@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");
 loader.lazyGetter(this, "_strings", () => {
   return Services.strings
   .createBundle("chrome://devtools-shared/locale/styleinspector.properties");
 });
 
 const PREF_ENABLE_MDN_DOCS_TOOLTIP =
--- a/devtools/client/netmonitor/test/browser_net_copy_as_curl.js
+++ b/devtools/client/netmonitor/test/browser_net_copy_as_curl.js
@@ -9,34 +9,34 @@ function test() {
   initNetMonitor(CURL_URL).then(([aTab, aDebuggee, aMonitor]) => {
     info("Starting test... ");
 
     const EXPECTED_POSIX_RESULT = [
       "curl",
       "'" + SIMPLE_SJS + "'",
       "-H 'Host: example.com'",
       "-H 'User-Agent: " + navigator.userAgent + "'",
-      "-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'",
+      "-H 'Accept: */*'",
       "-H 'Accept-Language: " + navigator.language + "'",
       "--compressed",
       "-H 'x-custom-header-1: Custom value'",
       "-H 'x-custom-header-2: 8.8.8.8'",
       "-H 'x-custom-header-3: Mon, 3 Mar 2014 11:11:11 GMT'",
       "-H 'Referer: " + CURL_URL + "'",
       "-H 'Connection: keep-alive'",
       "-H 'Pragma: no-cache'",
       "-H 'Cache-Control: no-cache'"
     ].join(" ");
 
     const EXPECTED_WIN_RESULT = [
       "curl",
       '"' + SIMPLE_SJS + '"',
       '-H "Host: example.com"',
       '-H "User-Agent: ' + navigator.userAgent + '"',
-      '-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"',
+      '-H "Accept: */*"',
       '-H "Accept-Language: ' + navigator.language + '"',
       "--compressed",
       '-H "x-custom-header-1: Custom value"',
       '-H "x-custom-header-2: 8.8.8.8"',
       '-H "x-custom-header-3: Mon, 3 Mar 2014 11:11:11 GMT"',
       '-H "Referer: ' + CURL_URL + '"',
       '-H "Connection: keep-alive"',
       '-H "Pragma: no-cache"',
--- a/devtools/shared/async-utils.js
+++ b/devtools/shared/async-utils.js
@@ -8,17 +8,16 @@
  * Helpers for async functions. Async functions are generator functions that are
  * run by Tasks. An async function returns a Promise for the resolution of the
  * function. When the function returns, the promise is resolved with the
  * returned value. If it throws the promise rejects with the thrown error.
  *
  * See Task documentation at https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Task.jsm.
  */
 
-var {Cu} = require("chrome");
 var {Task} = require("devtools/shared/task");
 var Promise = require("promise");
 
 /**
  * Create an async function that only executes once per instance of an object.
  * Once called on a given object, the same promise will be returned for any
  * future calls for that object.
  *
@@ -49,17 +48,17 @@ exports.asyncOnce = function asyncOnce(f
  * @param  Boolean useCapture
  *         Should we initiate the capture phase?
  * @return Promise
  *         The promise resolved with the event object when the event first
  *         happens
  */
 exports.listenOnce = function listenOnce(element, event, useCapture) {
   return new Promise(function (resolve, reject) {
-    var onEvent = function (ev) {
+    let onEvent = function (ev) {
       element.removeEventListener(event, onEvent, useCapture);
       resolve(ev);
     };
     element.addEventListener(event, onEvent, useCapture);
   });
 };
 
 /**
--- a/devtools/shared/indentation.js
+++ b/devtools/shared/indentation.js
@@ -1,17 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
 /* vim:set ts=2 sw=2 sts=2 et tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { Cu } = require("chrome");
 const Services = require("Services");
 
 const EXPAND_TAB = "devtools.editor.expandtab";
 const TAB_SIZE = "devtools.editor.tabsize";
 const DETECT_INDENT = "devtools.editor.detectindentation";
 const DETECT_INDENT_MAX_LINES = 500;
 
 /**
--- a/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js
+++ b/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js
@@ -114,17 +114,17 @@ function setPermissions() {
       sendAsyncMessage('test:InputMethod:oninput', {
         from: 'input',
         value: this.value
       });
     };
 
     input.onblur = function() {
       // "Expected" lost of focus since the test is finished.
-      if (input.value === '#0#1hello') {
+      if (input.value === 'hello#0#1') {
         return;
       }
 
       sendAsyncMessage('test:InputMethod:oninput', {
         from: 'input',
         error: true,
         value: 'Unexpected lost of focus on the input frame!'
       });
@@ -223,17 +223,17 @@ function next(msg) {
 
         case 'im1':
           is(false, 'Shouldn\'t be hearing anything from second frame.');
 
           break;
 
         case 'input':
           if (gFrameMsgCounts.input === 1) {
-            is(value, '#0hello',
+            is(value, 'hello#0',
               'Failed to get correct input from the first iframe.');
           } else {
             ok(false, 'Unexpected multiple messages from input.')
           }
 
           break;
       }
 
@@ -278,17 +278,17 @@ function next(msg) {
           } else {
             ok(false, 'Unexpected multiple messages from im0.')
           }
 
           break;
 
         case 'input':
           if (gFrameMsgCounts.input === 2) {
-            is(value, '#0#1hello',
+            is(value, 'hello#0#1',
                'Failed to get correct input from the second iframe.');
           } else {
             ok(false, 'Unexpected multiple messages from input.')
           }
           break;
       }
 
       if (gFrameMsgCounts.input !== 2 ||
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1680,17 +1680,21 @@ int32_t
 CanvasRenderingContext2D::GetHeight() const
 {
   return mHeight;
 }
 
 NS_IMETHODIMP
 CanvasRenderingContext2D::SetDimensions(int32_t aWidth, int32_t aHeight)
 {
-  ClearTarget();
+  bool retainBuffer = false;
+  if (aWidth == mWidth && aHeight == mHeight) {
+    retainBuffer = true;
+  }
+  ClearTarget(retainBuffer);
 
   // Zero sized surfaces can cause problems.
   mZero = false;
   if (aHeight == 0) {
     aHeight = 1;
     mZero = true;
   }
   if (aWidth == 0) {
@@ -1699,20 +1703,33 @@ CanvasRenderingContext2D::SetDimensions(
   }
   mWidth = aWidth;
   mHeight = aHeight;
 
   return NS_OK;
 }
 
 void
-CanvasRenderingContext2D::ClearTarget()
-{
+CanvasRenderingContext2D::ClearTarget(bool aRetainBuffer)
+{
+  RefPtr<PersistentBufferProvider> provider = mBufferProvider;
+  if (aRetainBuffer && provider) {
+    // We should reset the buffer data before reusing the buffer.
+    if (mTarget) {
+      mTarget->SetTransform(Matrix());
+    }
+    ClearRect(0, 0, mWidth, mHeight);
+  }
+
   Reset();
 
+  if (aRetainBuffer) {
+    mBufferProvider = provider;
+  }
+
   mResetLayer = true;
 
   // set up the initial canvas defaults
   mStyleStack.Clear();
   mPathBuilder = nullptr;
   mPath = nullptr;
   mDSPathBuilder = nullptr;
 
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -652,17 +652,17 @@ protected:
   /**
    * Cf. OnStableState.
    */
   void ScheduleStableStateCallback();
 
   /**
    * Disposes an old target and prepares to lazily create a new target.
    */
-  void ClearTarget();
+  void ClearTarget(bool aRetainBuffer = false);
 
   /*
    * Returns the target to the buffer provider. i.e. this will queue a frame for
    * rendering.
    */
   void ReturnTarget();
 
   /**
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -5652,18 +5652,18 @@ HTMLInputElement::SetRangeText(const nsA
     return;
   }
 
   int32_t start, end;
   aRv = GetSelectionRange(&start, &end);
   if (aRv.Failed()) {
     nsTextEditorState* state = GetEditorState();
     if (state && state->IsSelectionCached()) {
-      start = state->GetSelectionProperties().mStart;
-      end = state->GetSelectionProperties().mEnd;
+      start = state->GetSelectionProperties().GetStart();
+      end = state->GetSelectionProperties().GetEnd();
       aRv = NS_OK;
     }
   }
 
   SetRangeText(aReplacement, start, end, mozilla::dom::SelectionMode::Preserve,
                aRv, start, end);
 }
 
@@ -5695,18 +5695,18 @@ HTMLInputElement::SetRangeText(const nsA
     aEnd = inputValueLength;
   }
 
   if (aSelectionStart == -1 && aSelectionEnd == -1) {
     aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
     if (aRv.Failed()) {
       nsTextEditorState* state = GetEditorState();
       if (state && state->IsSelectionCached()) {
-        aSelectionStart = state->GetSelectionProperties().mStart;
-        aSelectionEnd = state->GetSelectionProperties().mEnd;
+        aSelectionStart = state->GetSelectionProperties().GetStart();
+        aSelectionEnd = state->GetSelectionProperties().GetEnd();
         aRv = NS_OK;
       }
     }
   }
 
   if (aStart <= aEnd) {
     value.Replace(aStart, aEnd - aStart, aReplacement);
     nsresult rv =
@@ -5765,17 +5765,17 @@ HTMLInputElement::GetSelectionStart(Erro
 {
   int32_t selEnd, selStart;
   aRv = GetSelectionRange(&selStart, &selEnd);
 
   if (aRv.Failed()) {
     nsTextEditorState* state = GetEditorState();
     if (state && state->IsSelectionCached()) {
       aRv = NS_OK;
-      return state->GetSelectionProperties().mStart;
+      return state->GetSelectionProperties().GetStart();
     }
   }
 
   return selStart;
 }
 
 NS_IMETHODIMP
 HTMLInputElement::GetSelectionStart(int32_t* aSelectionStart)
@@ -5787,17 +5787,17 @@ HTMLInputElement::GetSelectionStart(int3
   return rv.StealNSResult();
 }
 
 void
 HTMLInputElement::SetSelectionStart(int32_t aSelectionStart, ErrorResult& aRv)
 {
   nsTextEditorState* state = GetEditorState();
   if (state && state->IsSelectionCached()) {
-    state->GetSelectionProperties().mStart = aSelectionStart;
+    state->GetSelectionProperties().SetStart(aSelectionStart);
     return;
   }
 
   nsAutoString direction;
   aRv = GetSelectionDirection(direction);
   if (aRv.Failed()) {
     return;
   }
@@ -5829,17 +5829,17 @@ HTMLInputElement::GetSelectionEnd(ErrorR
 {
   int32_t selStart, selEnd;
   aRv = GetSelectionRange(&selStart, &selEnd);
 
   if (aRv.Failed()) {
     nsTextEditorState* state = GetEditorState();
     if (state && state->IsSelectionCached()) {
       aRv = NS_OK;
-      return state->GetSelectionProperties().mEnd;
+      return state->GetSelectionProperties().GetEnd();
     }
   }
 
   return selEnd;
 }
 
 NS_IMETHODIMP
 HTMLInputElement::GetSelectionEnd(int32_t* aSelectionEnd)
@@ -5851,17 +5851,17 @@ HTMLInputElement::GetSelectionEnd(int32_
   return rv.StealNSResult();
 }
 
 void
 HTMLInputElement::SetSelectionEnd(int32_t aSelectionEnd, ErrorResult& aRv)
 {
   nsTextEditorState* state = GetEditorState();
   if (state && state->IsSelectionCached()) {
-    state->GetSelectionProperties().mEnd = aSelectionEnd;
+    state->GetSelectionProperties().SetEnd(aSelectionEnd);
     return;
   }
 
   nsAutoString direction;
   aRv = GetSelectionDirection(direction);
   if (aRv.Failed()) {
     return;
   }
@@ -5935,17 +5935,17 @@ HTMLInputElement::GetSelectionDirection(
     if (NS_SUCCEEDED(rv)) {
       DirectionToName(dir, aDirection);
     }
   }
 
   if (NS_FAILED(rv)) {
     nsTextEditorState* state = GetEditorState();
     if (state && state->IsSelectionCached()) {
-      DirectionToName(state->GetSelectionProperties().mDirection, aDirection);
+      DirectionToName(state->GetSelectionProperties().GetDirection(), aDirection);
       return;
     }
   }
 
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 }
@@ -5964,17 +5964,17 @@ HTMLInputElement::SetSelectionDirection(
   nsTextEditorState* state = GetEditorState();
   if (state && state->IsSelectionCached()) {
     nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eNone;
     if (aDirection.EqualsLiteral("forward")) {
       dir = nsITextControlFrame::eForward;
     } else if (aDirection.EqualsLiteral("backward")) {
       dir = nsITextControlFrame::eBackward;
     }
-    state->GetSelectionProperties().mDirection = dir;
+    state->GetSelectionProperties().SetDirection(dir);
     return;
   }
 
   int32_t start, end;
   aRv = GetSelectionRange(&start, &end);
   if (!aRv.Failed()) {
     aRv = SetSelectionRange(start, end, aDirection);
   }
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1207,17 +1207,17 @@ void HTMLMediaElement::SelectResource()
       NS_ASSERTION(!mIsLoadingFromSourceChildren,
         "Should think we're not loading from source children by default");
 
       RemoveMediaElementFromURITable();
       mLoadingSrc = uri;
       mMediaSource = mSrcMediaSource;
       UpdatePreloadAction();
       if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
-          !IsMediaStreamURI(mLoadingSrc)) {
+          !IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
         // preload:none media, suspend the load here before we make any
         // network requests.
         SuspendLoad();
         return;
       }
 
       rv = LoadResource();
       if (NS_SUCCEEDED(rv)) {
@@ -1362,17 +1362,17 @@ void HTMLMediaElement::LoadFromSourceChi
 
     RemoveMediaElementFromURITable();
     mLoadingSrc = uri;
     mMediaSource = childSrc->GetSrcMediaSource();
     NS_ASSERTION(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING,
                  "Network state should be loading");
 
     if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
-        !IsMediaStreamURI(mLoadingSrc)) {
+        !IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
       // preload:none media, suspend the load here before we make any
       // network requests.
       SuspendLoad();
       return;
     }
 
     if (NS_SUCCEEDED(LoadResource())) {
       return;
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -666,17 +666,17 @@ HTMLTextAreaElement::GetSelectionStart(i
 
 uint32_t
 HTMLTextAreaElement::GetSelectionStart(ErrorResult& aError)
 {
   int32_t selStart, selEnd;
   nsresult rv = GetSelectionRange(&selStart, &selEnd);
 
   if (NS_FAILED(rv) && mState.IsSelectionCached()) {
-    return mState.GetSelectionProperties().mStart;
+    return mState.GetSelectionProperties().GetStart();
   }
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
   }
   return selStart;
 }
 
 NS_IMETHODIMP
@@ -686,17 +686,17 @@ HTMLTextAreaElement::SetSelectionStart(i
   SetSelectionStart(aSelectionStart, error);
   return error.StealNSResult();
 }
 
 void
 HTMLTextAreaElement::SetSelectionStart(uint32_t aSelectionStart, ErrorResult& aError)
 {
   if (mState.IsSelectionCached()) {
-    mState.GetSelectionProperties().mStart = aSelectionStart;
+    mState.GetSelectionProperties().SetStart(aSelectionStart);
     return;
   }
 
   nsAutoString direction;
   nsresult rv = GetSelectionDirection(direction);
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
     return;
@@ -729,17 +729,17 @@ HTMLTextAreaElement::GetSelectionEnd(int
 
 uint32_t
 HTMLTextAreaElement::GetSelectionEnd(ErrorResult& aError)
 {
   int32_t selStart, selEnd;
   nsresult rv = GetSelectionRange(&selStart, &selEnd);
 
   if (NS_FAILED(rv) && mState.IsSelectionCached()) {
-    return mState.GetSelectionProperties().mEnd;
+    return mState.GetSelectionProperties().GetEnd();
   }
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
   }
   return selEnd;
 }
 
 NS_IMETHODIMP
@@ -749,17 +749,17 @@ HTMLTextAreaElement::SetSelectionEnd(int
   SetSelectionEnd(aSelectionEnd, error);
   return error.StealNSResult();
 }
 
 void
 HTMLTextAreaElement::SetSelectionEnd(uint32_t aSelectionEnd, ErrorResult& aError)
 {
   if (mState.IsSelectionCached()) {
-    mState.GetSelectionProperties().mEnd = aSelectionEnd;
+    mState.GetSelectionProperties().SetEnd(aSelectionEnd);
     return;
   }
 
   nsAutoString direction;
   nsresult rv = GetSelectionDirection(direction);
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
     return;
@@ -826,17 +826,17 @@ HTMLTextAreaElement::GetSelectionDirecti
     rv = textControlFrame->GetSelectionRange(nullptr, nullptr, &dir);
     if (NS_SUCCEEDED(rv)) {
       DirectionToName(dir, aDirection);
     }
   }
 
   if (NS_FAILED(rv)) {
     if (mState.IsSelectionCached()) {
-      DirectionToName(mState.GetSelectionProperties().mDirection, aDirection);
+      DirectionToName(mState.GetSelectionProperties().GetDirection(), aDirection);
       return;
     }
     aError.Throw(rv);
   }
 }
 
 NS_IMETHODIMP
 HTMLTextAreaElement::SetSelectionDirection(const nsAString& aDirection)
@@ -851,17 +851,17 @@ HTMLTextAreaElement::SetSelectionDirecti
 {
   if (mState.IsSelectionCached()) {
     nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eNone;
     if (aDirection.EqualsLiteral("forward")) {
       dir = nsITextControlFrame::eForward;
     } else if (aDirection.EqualsLiteral("backward")) {
       dir = nsITextControlFrame::eBackward;
     }
-    mState.GetSelectionProperties().mDirection = dir;
+    mState.GetSelectionProperties().SetDirection(dir);
     return;
   }
 
   int32_t start, end;
   nsresult rv = GetSelectionRange(&start, &end);
   if (NS_SUCCEEDED(rv)) {
     rv = SetSelectionRange(start, end, aDirection);
   }
@@ -918,18 +918,18 @@ HTMLTextAreaElement::SetSelectionRange(u
 void
 HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
                                   ErrorResult& aRv)
 {
   int32_t start, end;
   aRv = GetSelectionRange(&start, &end);
   if (aRv.Failed()) {
     if (mState.IsSelectionCached()) {
-      start = mState.GetSelectionProperties().mStart;
-      end = mState.GetSelectionProperties().mEnd;
+      start = mState.GetSelectionProperties().GetStart();
+      end = mState.GetSelectionProperties().GetEnd();
       aRv = NS_OK;
     }
   }
 
   SetRangeText(aReplacement, start, end, mozilla::dom::SelectionMode::Preserve,
                aRv, start, end);
 }
 
@@ -956,18 +956,18 @@ HTMLTextAreaElement::SetRangeText(const 
   if (aEnd > inputValueLength) {
     aEnd = inputValueLength;
   }
 
   if (aSelectionStart == -1 && aSelectionEnd == -1) {
     aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
     if (aRv.Failed()) {
       if (mState.IsSelectionCached()) {
-        aSelectionStart = mState.GetSelectionProperties().mStart;
-        aSelectionEnd = mState.GetSelectionProperties().mEnd;
+        aSelectionStart = mState.GetSelectionProperties().GetStart();
+        aSelectionEnd = mState.GetSelectionProperties().GetEnd();
         aRv = NS_OK;
       }
     }
   }
 
   if (aStart <= aEnd) {
     value.Replace(aStart, aEnd - aStart, aReplacement);
     nsresult rv =
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -98,21 +98,23 @@ public:
 
     AutoHideSelectionChanges hideSelectionChanges
       (mFrame->GetConstFrameSelection());
 
     if (mFrame) {
       // SetSelectionRange leads to Selection::AddRange which flushes Layout -
       // need to block script to avoid nested PrepareEditor calls (bug 642800).
       nsAutoScriptBlocker scriptBlocker;
-       nsTextEditorState::SelectionProperties& properties =
-         mTextEditorState->GetSelectionProperties();
-       mFrame->SetSelectionRange(properties.mStart,
-                                 properties.mEnd,
-                                 properties.mDirection);
+      nsTextEditorState::SelectionProperties& properties =
+        mTextEditorState->GetSelectionProperties();
+      if (properties.IsDirty()) {
+        mFrame->SetSelectionRange(properties.GetStart(),
+                                  properties.GetEnd(),
+                                  properties.GetDirection());
+      }
       if (!mTextEditorState->mSelectionRestoreEagerInit) {
         mTextEditorState->HideSelectionIfBlurred();
       }
       mTextEditorState->mSelectionRestoreEagerInit = false;
     }
 
     if (mTextEditorState) {
       mTextEditorState->FinishedRestoringSelection();
@@ -1604,30 +1606,36 @@ nsTextEditorState::UnbindFromFrame(nsTex
   }
 
   // Save our selection state if needed.
   // Note that nsTextControlFrame::GetSelectionRange attempts to initialize the
   // editor before grabbing the range, and because this is not an acceptable
   // side effect for unbinding from a text control frame, we need to call
   // GetSelectionRange before calling DestroyEditor, and only if
   // mEditorInitialized indicates that we actually have an editor available.
+  int32_t start = 0, end = 0;
+  nsITextControlFrame::SelectionDirection direction =
+    nsITextControlFrame::eForward;
   if (mEditorInitialized) {
     HTMLInputElement* number = GetParentNumberControl(aFrame);
     if (number) {
       // If we are inside a number control, cache the selection on the
       // parent control, because this text editor state will be destroyed
       // together with the native anonymous text control.
       SelectionProperties props;
-      mBoundFrame->GetSelectionRange(&props.mStart, &props.mEnd,
-                                     &props.mDirection);
+      mBoundFrame->GetSelectionRange(&start, &end, &direction);
+      props.SetStart(start);
+      props.SetEnd(end);
+      props.SetDirection(direction);
       number->SetSelectionProperties(props);
     } else {
-      mBoundFrame->GetSelectionRange(&mSelectionProperties.mStart,
-                                     &mSelectionProperties.mEnd,
-                                     &mSelectionProperties.mDirection);
+      mBoundFrame->GetSelectionRange(&start, &end, &direction);
+      mSelectionProperties.SetStart(start);
+      mSelectionProperties.SetEnd(end);
+      mSelectionProperties.SetDirection(direction);
       mSelectionCached = true;
     }
   }
 
   // Destroy our editor
   DestroyEditor();
 
   // Clean up the controller
--- a/dom/html/nsTextEditorState.h
+++ b/dom/html/nsTextEditorState.h
@@ -193,38 +193,74 @@ public:
     return mTextCtrlElement->GetRows();
   }
 
   // placeholder methods
   void UpdatePlaceholderVisibility(bool aNotify);
   bool GetPlaceholderVisibility() {
     return mPlaceholderVisibility;
   }
-  void UpdatePlaceholderText(bool aNotify); 
+  void UpdatePlaceholderText(bool aNotify);
 
   /**
    * Get the maxlength attribute
    * @param aMaxLength the value of the max length attr
    * @returns false if attr not defined
    */
   bool GetMaxLength(int32_t* aMaxLength);
 
   void ClearValueCache() { mCachedValue.Truncate(); }
 
   void HideSelectionIfBlurred();
 
   struct SelectionProperties {
-    SelectionProperties() : mStart(0), mEnd(0),
-      mDirection(nsITextControlFrame::eForward) {}
-    bool IsDefault() const {
-      return mStart == 0 && mEnd == 0 &&
-             mDirection == nsITextControlFrame::eForward;
-    }
-    int32_t mStart, mEnd;
-    nsITextControlFrame::SelectionDirection mDirection;
+    public:
+      SelectionProperties() : mStart(0), mEnd(0),
+        mDirection(nsITextControlFrame::eForward) {}
+      bool IsDefault() const
+      {
+        return mStart == 0 && mEnd == 0 &&
+               mDirection == nsITextControlFrame::eForward;
+      }
+      int32_t GetStart() const
+      {
+        return mStart;
+      }
+      void SetStart(int32_t value)
+      {
+        mIsDirty = true;
+        mStart = value;
+      }
+      int32_t GetEnd() const
+      {
+        return mEnd;
+      }
+      void SetEnd(int32_t value)
+      {
+        mIsDirty = true;
+        mEnd = value;
+      }
+      nsITextControlFrame::SelectionDirection GetDirection() const
+      {
+        return mDirection;
+      }
+      void SetDirection(nsITextControlFrame::SelectionDirection value)
+      {
+        mIsDirty = true;
+        mDirection = value;
+      }
+      // return true only if mStart, mEnd, or mDirection have been modified
+      bool IsDirty() const
+      {
+        return mIsDirty;
+      }
+    private:
+      int32_t mStart, mEnd;
+      bool mIsDirty = false;
+      nsITextControlFrame::SelectionDirection mDirection;
   };
 
   bool IsSelectionCached() const;
   SelectionProperties& GetSelectionProperties();
   void WillInitEagerly() { mSelectionRestoreEagerInit = true; }
   bool HasNeverInitializedBefore() const { return !mEverInited; }
 
   void UpdateEditableState(bool aNotify) {
--- a/dom/html/test/test_bug332246.html
+++ b/dom/html/test/test_bug332246.html
@@ -32,40 +32,44 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 332246 **/
 
+function isWithFuzz(itIs, itShouldBe, fuzz, description) {
+  ok(Math.abs(itIs - itShouldBe) <= fuzz, `${description} - expected a value between ${itShouldBe - fuzz} and ${itShouldBe + fuzz}, got ${itIs}`);
+}
+
 var a1 = document.getElementById('a1');
 var a2 = document.getElementById('a2');
-is(a1.scrollHeight, 400, "Wrong a1.scrollHeight");
+isWithFuzz(a1.scrollHeight, 400, 1, "Wrong a1.scrollHeight");
 is(a1.offsetHeight, 100, "Wrong a1.offsetHeight");
 a2.scrollIntoView(true);
 is(a1.scrollTop, 100, "Wrong scrollTop value after a2.scrollIntoView(true)");
 a2.scrollIntoView(false);
 is(a1.scrollTop, 200, "Wrong scrollTop value after a2.scrollIntoView(false)");
 
 var b1 = document.getElementById('b1');
 var b2 = document.getElementById('b2');
-is(b1.scrollHeight, 420, "Wrong b1.scrollHeight");
+isWithFuzz(b1.scrollHeight, 420, 1, "Wrong b1.scrollHeight");
 is(b1.offsetHeight, 100, "Wrong b1.offsetHeight");
 b2.scrollIntoView(true);
 is(b1.scrollTop, 100, "Wrong scrollTop value after b2.scrollIntoView(true)");
 b2.scrollIntoView(false);
 is(b1.scrollTop, 220, "Wrong scrollTop value after b2.scrollIntoView(false)");
 
 var c1 = document.getElementById('c1');
 var c2 = document.getElementById('c2');
-is(c1.scrollHeight, 320, "Wrong c1.scrollHeight");
+isWithFuzz(c1.scrollHeight, 320, 1, "Wrong c1.scrollHeight");
 is(c1.offsetHeight, 100, "Wrong c1.offsetHeight");
 c2.scrollIntoView(true);
 is(c1.scrollTop, 100, "Wrong scrollTop value after c2.scrollIntoView(true)");
 c2.scrollIntoView(false);
-is(c1.scrollTop, 220, "Wrong scrollTop value after c2.scrollIntoView(false)");
+isWithFuzz(c1.scrollTop, 220, 1, "Wrong scrollTop value after c2.scrollIntoView(false)");
 
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/html/test/test_bug674558.html
+++ b/dom/html/test/test_bug674558.html
@@ -46,18 +46,18 @@ function startTest() {
 }
 
 function test(ctor) {
   var elem = ctor();
   ok(true, "Testing " + name(elem));
 
   ok("selectionDirection" in elem, "elem should have the selectionDirection property");
 
-  is(elem.selectionStart, 0, "Default value");
-  is(elem.selectionEnd, 0, "Default value");
+  is(elem.selectionStart, elem.value.length, "Default value");
+  is(elem.selectionEnd, elem.value.length, "Default value");
   is(elem.selectionDirection, "forward", "Default value");
 
   var content = document.getElementById("content");
   content.appendChild(elem);
 
   function flush() { document.body.clientWidth; }
   function hide() {
     content.style.display = "none";
@@ -65,18 +65,18 @@ function test(ctor) {
   }
   function show() {
     content.style.display = "";
     flush();
   }
 
   elem.value = "foobar";
 
-  is(elem.selectionStart, 0, "Default value");
-  is(elem.selectionEnd, 0, "Default value");
+  is(elem.selectionStart, elem.value.length, "Default value");
+  is(elem.selectionEnd, elem.value.length, "Default value");
   is(elem.selectionDirection, "forward", "Default value");
 
   elem.setSelectionRange(1, 3);
   is(elem.selectionStart, 1, "Correct value");
   is(elem.selectionEnd, 3, "Correct value");
   is(elem.selectionDirection, "forward", "If not set, should default to forward");
 
   hide();
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -141,23 +141,26 @@ NS_IMPL_ISUPPORTS(MediaMemoryTracker, ns
 NS_IMPL_ISUPPORTS0(MediaDecoder)
 
 
 void
 MediaDecoder::ResourceCallback::Connect(MediaDecoder* aDecoder)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mDecoder = aDecoder;
+  mTimer = do_CreateInstance("@mozilla.org/timer;1");
 }
 
 void
 MediaDecoder::ResourceCallback::Disconnect()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mDecoder = nullptr;
+  mTimer->Cancel();
+  mTimer = nullptr;
 }
 
 MediaDecoderOwner*
 MediaDecoder::ResourceCallback::GetMediaOwner() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   return mDecoder ? mDecoder->GetOwner() : nullptr;
 }
@@ -212,23 +215,40 @@ MediaDecoder::ResourceCallback::NotifyDe
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
     if (self->mDecoder) {
       self->mDecoder->DecodeError();
     }
   });
   AbstractThread::MainThread()->Dispatch(r.forget());
 }
 
+/* static */ void
+MediaDecoder::ResourceCallback::TimerCallback(nsITimer* aTimer, void* aClosure)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  ResourceCallback* thiz = static_cast<ResourceCallback*>(aClosure);
+  MOZ_ASSERT(thiz->mDecoder);
+  thiz->mDecoder->NotifyDataArrived();
+  thiz->mTimerArmed = false;
+}
+
 void
 MediaDecoder::ResourceCallback::NotifyDataArrived()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  if (mDecoder) {
-    mDecoder->NotifyDataArrived();
+  if (!mDecoder || mTimerArmed) {
+    return;
   }
+  // In situations where these notifications come from stochastic network
+  // activity, we can save significant computation by throttling the
+  // calls to MediaDecoder::NotifyDataArrived() which will update the buffer
+  // ranges of the reader.
+  mTimerArmed = true;
+  mTimer->InitWithFuncCallback(
+    TimerCallback, this, sDelay, nsITimer::TYPE_ONE_SHOT);
 }
 
 void
 MediaDecoder::ResourceCallback::NotifyBytesDownloaded()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mDecoder) {
     mDecoder->NotifyBytesDownloaded();
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -65,16 +65,20 @@ public:
       : mAtEnd(aAtEnd), mEventVisibility(aEventVisibility) {}
     bool mAtEnd;
     MediaDecoderEventVisibility mEventVisibility;
   };
 
   // Used to register with MediaResource to receive notifications which will
   // be forwarded to MediaDecoder.
   class ResourceCallback : public MediaResourceCallback {
+    // Throttle calls to MediaDecoder::NotifyDataArrived()
+    // to be at most once per 500ms.
+    static const uint32_t sDelay = 500;
+
   public:
     // Start to receive notifications from ResourceCallback.
     void Connect(MediaDecoder* aDecoder);
     // Called upon shutdown to stop receiving notifications.
     void Disconnect();
 
   private:
     /* MediaResourceCallback functions */
@@ -87,18 +91,22 @@ public:
     void NotifyDecodeError() override;
     void NotifyDataArrived() override;
     void NotifyBytesDownloaded() override;
     void NotifyDataEnded(nsresult aStatus) override;
     void NotifyPrincipalChanged() override;
     void NotifySuspendedStatusChanged() override;
     void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) override;
 
+    static void TimerCallback(nsITimer* aTimer, void* aClosure);
+
     // The decoder to send notifications. Main-thread only.
     MediaDecoder* mDecoder = nullptr;
+    nsCOMPtr<nsITimer> mTimer;
+    bool mTimerArmed = false;
   };
 
   typedef MozPromise<SeekResolveValue, bool /* aIgnored */, /* IsExclusive = */ true> SeekPromise;
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   // Enumeration for the valid play states (see mPlayState)
   enum PlayState {
--- a/dom/presentation/PresentationRequest.cpp
+++ b/dom/presentation/PresentationRequest.cpp
@@ -7,18 +7,21 @@
 #include "PresentationRequest.h"
 
 #include "ControllerConnectionCollection.h"
 #include "mozilla/dom/PresentationRequestBinding.h"
 #include "mozilla/dom/PresentationConnectionAvailableEvent.h"
 #include "mozilla/dom/Promise.h"
 #include "mozIThirdPartyUtil.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsIDocument.h"
 #include "nsIPresentationService.h"
+#include "nsIURI.h"
 #include "nsIUUIDGenerator.h"
+#include "nsNetUtil.h"
 #include "nsSandboxFlags.h"
 #include "nsServiceManagerUtils.h"
 #include "PresentationAvailability.h"
 #include "PresentationCallbacks.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
@@ -26,16 +29,41 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(Prese
                                    mAvailability)
 
 NS_IMPL_ADDREF_INHERITED(PresentationRequest, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(PresentationRequest, DOMEventTargetHelper)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationRequest)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
+static nsresult
+GetAbsoluteURL(const nsAString& aUrl,
+               nsIURI* aBaseUri,
+               nsIDocument* aDocument,
+               nsAString& aAbsoluteUrl)
+{
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_NewURI(getter_AddRefs(uri),
+                          aUrl,
+                          aDocument ? aDocument->GetDocumentCharacterSet().get()
+                                    : nullptr,
+                          aBaseUri);
+
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  nsAutoCString spec;
+  uri->GetSpec(spec);
+
+  aAbsoluteUrl = NS_ConvertUTF8toUTF16(spec);
+
+  return NS_OK;
+}
+
 /* static */ already_AddRefed<PresentationRequest>
 PresentationRequest::Constructor(const GlobalObject& aGlobal,
                                  const nsAString& aUrl,
                                  ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
   if (!window) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
@@ -43,17 +71,28 @@ PresentationRequest::Constructor(const G
   }
 
   // Ensure the URL is not empty.
   if (NS_WARN_IF(aUrl.IsEmpty())) {
     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     return nullptr;
   }
 
-  RefPtr<PresentationRequest> request = new PresentationRequest(window, aUrl);
+  // Resolve relative URL to absolute URL
+  nsCOMPtr<nsIURI> baseUri = window->GetDocBaseURI();
+
+  nsAutoString absoluteUrl;
+  nsresult rv = GetAbsoluteURL(aUrl, baseUri, window->GetExtantDoc(), absoluteUrl);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  RefPtr<PresentationRequest> request =
+    new PresentationRequest(window, absoluteUrl);
   return NS_WARN_IF(!request->Init()) ? nullptr : request.forget();
 }
 
 PresentationRequest::PresentationRequest(nsPIDOMWindowInner* aWindow,
                                          const nsAString& aUrl)
   : DOMEventTargetHelper(aWindow)
   , mUrl(aUrl)
 {
--- a/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.html
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.html
@@ -103,17 +103,17 @@ function setup() {
   });
 
   return Promise.resolve();
 }
 
 function testCreateRequest() {
   return new Promise(function(aResolve, aReject) {
     info('Sender: --- testCreateRequest ---');
-    request = new PresentationRequest(receiverUrl);
+    request = new PresentationRequest("file_presentation_1ua_receiver.html");
     request.getAvailability().then((aAvailability) => {
       aAvailability.onchange = function() {
         aAvailability.onchange = null;
         ok(aAvailability.value, "Sender: Device should be available.");
         aResolve();
       }
     }).catch((aError) => {
       ok(false, "Sender: Error occurred when getting availability: " + aError);
@@ -127,16 +127,17 @@ function testCreateRequest() {
 
 function testStartConnection() {
   return new Promise(function(aResolve, aReject) {
     request.start().then((aConnection) => {
       connection = aConnection;
       ok(connection, "Sender: Connection should be available.");
       ok(connection.id, "Sender: Connection ID should be set.");
       is(connection.state, "connecting", "The initial state should be connecting.");
+      is(connection.url, receiverUrl, "request URL should be expanded to absolute URL");
       connection.onconnect = function() {
         connection.onconnect = null;
         is(connection.state, "connected", "Connection should be connected.");
         presentationId = connection.id;
         aResolve();
       };
     }).catch((aError) => {
       ok(false, "Sender: Error occurred when establishing a connection: " + aError);
--- a/dom/presentation/tests/mochitest/test_presentation_dc_sender.html
+++ b/dom/presentation/tests/mochitest/test_presentation_dc_sender.html
@@ -17,17 +17,17 @@
 
 var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
 var frameScript = SpecialPowers.isMainProcess() ? gScript : contentScript;
 var request;
 var connection;
 
 function testSetup() {
   return new Promise(function(aResolve, aReject) {
-    request = new PresentationRequest("http://example.com");
+    request = new PresentationRequest("http://example.com/");
 
     request.getAvailability().then(
       function(aAvailability) {
         aAvailability.onchange = function() {
           aAvailability.onchange = null;
           ok(aAvailability.value, "Device should be available.");
           aResolve();
         }
@@ -179,17 +179,17 @@ function testReconnect() {
     info('--- testReconnect ---');
     gScript.addMessageListener('control-channel-established', function controlChannelEstablished() {
       gScript.removeMessageListener('control-channel-established', controlChannelEstablished);
       gScript.sendAsyncMessage("trigger-control-channel-open");
     });
 
     gScript.addMessageListener('start-reconnect', function startReconnectHandler(url) {
       gScript.removeMessageListener('start-reconnect', startReconnectHandler);
-      is(url, "http://example.com", "URLs should be the same.")
+      is(url, "http://example.com/", "URLs should be the same.")
       gScript.sendAsyncMessage('trigger-reconnected-acked', url);
     });
 
     gScript.addMessageListener('offer-sent', function offerSentHandler(aIsValid) {
       gScript.removeMessageListener('offer-sent', offerSentHandler);
       ok(aIsValid, "A valid offer is sent out.");
       gScript.sendAsyncMessage('trigger-incoming-answer');
     });
--- a/dom/presentation/tests/mochitest/test_presentation_reconnect.html
+++ b/dom/presentation/tests/mochitest/test_presentation_reconnect.html
@@ -39,17 +39,17 @@ function testSetup() {
           commandHandler[command.name](command);
         }
       } else if (/^DONE$/.exec(message)) {
         window.removeEventListener('message', listener);
         SimpleTest.finish();
       }
     }, false);
 
-    request = new PresentationRequest("http://example.com");
+    request = new PresentationRequest("http://example.com/");
 
     request.getAvailability().then(
       function(aAvailability) {
         aAvailability.onchange = function() {
           aAvailability.onchange = null;
           ok(aAvailability.value, "Device should be available.");
           aResolve();
         }
@@ -296,17 +296,17 @@ function testReconnectIframeClosedConnec
   });
 }
 
 function testReconnect() {
   return new Promise(function(aResolve, aReject) {
     info('--- testReconnect ---');
     gScript.addMessageListener('start-reconnect', function startReconnectHandler(url) {
       gScript.removeMessageListener('start-reconnect', startReconnectHandler);
-      is(url, "http://example.com", "URLs should be the same.");
+      is(url, "http://example.com/", "URLs should be the same.");
       gScript.sendAsyncMessage('trigger-reconnected-acked', url);
     });
 
     request.reconnect(connection.id).then(
       function(aConnection) {
         ok(aConnection, "Connection should be available.");
         ok(aConnection.id, "Connection ID should be set.");
         is(aConnection.state, "connecting", "The initial state should be connecting.");
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_sender.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_sender.html
@@ -15,17 +15,17 @@
 'use strict';
 
 var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
 var request;
 var connection;
 
 function testSetup() {
   return new Promise(function(aResolve, aReject) {
-    request = new PresentationRequest("http://example.com");
+    request = new PresentationRequest("http://example.com/");
 
     request.getAvailability().then(
       function(aAvailability) {
         aAvailability.onchange = function() {
           aAvailability.onchange = null;
           ok(aAvailability.value, "Device should be available.");
           aResolve();
         }
@@ -173,17 +173,17 @@ function testReconnect() {
     info('--- testReconnect ---');
     gScript.addMessageListener('control-channel-established', function controlChannelEstablished() {
       gScript.removeMessageListener('control-channel-established', controlChannelEstablished);
       gScript.sendAsyncMessage("trigger-control-channel-open");
     });
 
     gScript.addMessageListener('start-reconnect', function startReconnectHandler(url) {
       gScript.removeMessageListener('start-reconnect', startReconnectHandler);
-      is(url, "http://example.com", "URLs should be the same.")
+      is(url, "http://example.com/", "URLs should be the same.")
       gScript.sendAsyncMessage('trigger-reconnected-acked', url);
     });
 
     gScript.addMessageListener('offer-sent', function offerSentHandler() {
       gScript.removeMessageListener('offer-sent', offerSentHandler);
       gScript.sendAsyncMessage('trigger-incoming-transport');
     });
 
--- a/dom/tests/mochitest/general/test_offsets.html
+++ b/dom/tests/mochitest/general/test_offsets.html
@@ -7,18 +7,22 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
 
 <style>
   input {
     box-sizing: content-box;
   }
 </style>
 </head>
+
+<!-- We set a transform on the body element so that it creates a reference frame.
+     This makes sure that snapping of scrolled areas for the contained elements
+     is not influenced by offsets outside of this document. -->
 <body id="body" onload="setTimeout(testElements, 0, 'testelements', SimpleTest.finish);"
-      style="margin: 1px; border: 2px solid black; padding: 4px;">
+      style="margin: 1px; border: 2px solid black; padding: 4px; transform: translateY(1px);">
 
 <div id="testelements" style="margin: 0; border: 0; padding: 0;">
   <div id="div1" style="margin: 0; margin-left: 6px; margin-top: 2px; border: 1px solid green; padding: 6px; width: 50px; height: 20px"
          _offsetLeft="13" _offsetTop="9" _offsetWidth="64" _offsetHeight="34"
          _scrollWidth="62" _scrollHeight="32"
          _clientLeft="1" _clientTop="1" _clientWidth="62" _clientHeight="32"></div>
   <div id="noscroll" style="margin: 2px; border: 1px solid blue; padding: 3px;"
        _offsetLeft="10" _offsetTop="12" _offsetWidth="64" _offsetHeight="34"
@@ -50,17 +54,17 @@
   <div id="fixed" style="position: fixed; margin: 2px; border: 1px solid orange; padding: 7px; left: 87px; top: 12px;">
     This is some fixed positioned text.
     <div id="fixed-block" _offsetParent="fixed">
       <div id="fixed-replaced" _offsetParent="fixed" style="margin: 1px; border: 0; padding: 3px;"></div>
     </div>
   </div>
 
   <div id="scrollbox"
-       style="overflow: scroll; padding-left: 0px; margin: 3px; border: 4px solid green; max-width: 80px; max-height: 70px;"
+       style="overflow: scroll; padding-left: 0px; margin: 3px; border: 4px solid green; max-width: 80px; max-height: 70px"
        _scrollWidth="62" _scrollHeight="32"
        _clientLeft="1" _clientTop="1" _clientWidth="62" _clientHeight="32"><p id="p1" style="margin: 0; padding: 0;">One</p>
     <p id="p2">Two</p>
     <p id="scrollchild">Three</p>
     <p id="lastlinebox" style="margin: 0; padding: 0;"><input id="lastline" type="button"
                                style="margin: 0px; border: 2px solid red;"
                                value="This button is much longer than the others">
   </p></div>
--- a/dom/tests/mochitest/general/test_offsets.js
+++ b/dom/tests/mochitest/general/test_offsets.js
@@ -176,22 +176,35 @@ function checkClientState(element, left,
 }
 
 function checkCoord(element, type, val, testname)
 {
   if (val != -10000)
     is(element[type], Math.round(val), testname + " " + type);
 }
 
+function checkCoordFuzzy(element, type, val, fuzz, testname)
+{
+  if (val != -10000)
+    ok(Math.abs(element[type] - Math.round(val)) <= fuzz, testname + " " + type);
+}
+
 function checkCoords(element, type, left, top, width, height, testname)
 {
   checkCoord(element, type + "Left", left, testname);
   checkCoord(element, type + "Top", top, testname);
-  checkCoord(element, type + "Width", width, testname);
-  checkCoord(element, type + "Height", height, testname);
+
+  if (type == "scroll") {
+    // scrollWidth and scrollHeight can deviate by 1 pixel due to snapping.
+    checkCoordFuzzy(element, type + "Width", width, 1, testname);
+    checkCoordFuzzy(element, type + "Height", height, 1, testname);
+  } else {
+    checkCoord(element, type + "Width", width, testname);
+    checkCoord(element, type + "Height", height, testname);
+  }
 
   if (element instanceof SVGElement)
     return;
 
   if (element.id == "outerpopup" && !element.parentNode.open) // closed popup
     return;
 
   if (element.id == "div-displaynone" || element.id == "nonappended") // hidden elements
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -2470,16 +2470,25 @@ XMLHttpRequestMainThread::SendInternal(c
 
     if (!IsSystemXHR()) {
       nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
       nsCOMPtr<nsIDocument> doc = owner ? owner->GetExtantDoc() : nullptr;
       nsContentUtils::SetFetchReferrerURIWithPolicy(mPrincipal, doc,
                                                     httpChannel, mozilla::net::RP_Default);
     }
 
+    // If the user hasn't overridden the Accept header, set it to */* as per spec
+    nsAutoCString acceptHeader;
+    GetAuthorRequestHeaderValue("accept", acceptHeader);
+    if (acceptHeader.IsVoid()) {
+      httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
+                                    NS_LITERAL_CSTRING("*/*"),
+                                    false);
+    }
+
     // Some extensions override the http protocol handler and provide their own
     // implementation. The channels returned from that implementation doesn't
     // seem to always implement the nsIUploadChannel2 interface, presumably
     // because it's a new interface.
     // Eventually we should remove this and simply require that http channels
     // implement the new interface.
     // See bug 529041
     nsCOMPtr<nsIUploadChannel2> uploadChannel2 =
@@ -3509,20 +3518,20 @@ XMLHttpRequestMainThread::EnsureXPCOMifi
 }
 
 bool
 XMLHttpRequestMainThread::ShouldBlockAuthPrompt()
 {
   // Verify that it's ok to prompt for credentials here, per spec
   // http://xhr.spec.whatwg.org/#the-send%28%29-method
 
-  for (RequestHeader& requestHeader : mAuthorRequestHeaders) {
-    if (requestHeader.name.EqualsLiteral("authorization")) {
-      return true;
-    }
+  nsAutoCString contentType;
+  GetAuthorRequestHeaderValue("authorization", contentType);
+  if (!contentType.IsVoid()) {
+    return true;
   }
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = mChannel->GetURI(getter_AddRefs(uri));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
 
--- a/gfx/src/nsRect.cpp
+++ b/gfx/src/nsRect.cpp
@@ -1,30 +1,44 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsRect.h"
 #include "mozilla/gfx/Types.h"          // for NS_SIDE_BOTTOM, etc
+#include "mozilla/CheckedInt.h"         // for CheckedInt
 #include "nsDeviceContext.h"            // for nsDeviceContext
 #include "nsString.h"               // for nsAutoString, etc
 #include "nsMargin.h"                   // for nsMargin
 
 static_assert((int(NS_SIDE_TOP) == 0) &&
               (int(NS_SIDE_RIGHT) == 1) &&
               (int(NS_SIDE_BOTTOM) == 2) &&
               (int(NS_SIDE_LEFT) == 3),
               "The mozilla::css::Side sequence must match the nsMargin nscoord sequence");
 
 const mozilla::gfx::IntRect& GetMaxSizedIntRect() {
   static const mozilla::gfx::IntRect r(0, 0, INT32_MAX, INT32_MAX);
   return r;
 }
 
+
+bool nsRect::Overflows() const {
+#ifdef NS_COORD_IS_FLOAT
+  return false;
+#else
+  mozilla::CheckedInt<int32_t> xMost = this->x;
+  xMost += this->width;
+  mozilla::CheckedInt<int32_t> yMost = this->y;
+  yMost += this->height;
+  return !xMost.isValid() || !yMost.isValid();
+#endif
+}
+
 #ifdef DEBUG
 // Diagnostics
 
 FILE* operator<<(FILE* out, const nsRect& rect)
 {
   nsAutoString tmp;
 
   // Output the coordinates in fractional pixels so they're easier to read
--- a/gfx/src/nsRect.h
+++ b/gfx/src/nsRect.h
@@ -124,16 +124,19 @@ struct nsRect :
   {
     *this = aRect1.SaturatingUnion(aRect2);
   }
   void SaturatingUnionRectEdges(const nsRect& aRect1, const nsRect& aRect2)
   {
     *this = aRect1.SaturatingUnionEdges(aRect2);
   }
 
+  // Return whether this rect's right or bottom edge overflow int32.
+  bool Overflows() const;
+
   /**
    * Return this rect scaled to a different appunits per pixel (APP) ratio.
    * In the RoundOut version we make the rect the smallest rect containing the
    * unrounded result. In the RoundIn version we make the rect the largest rect
    * contained in the unrounded result.
    * @param aFromAPP the APP to scale from
    * @param aToAPP the APP to scale to
    * @note this can turn an empty rectangle into a non-empty rectangle
--- a/gfx/ycbcr/YCbCrUtils.cpp
+++ b/gfx/ycbcr/YCbCrUtils.cpp
@@ -113,17 +113,16 @@ ConvertYCbCrToRGB(const layers::PlanarYC
                         aData.mPicSize.width,
                         aData.mPicSize.height,
                         aDestSize.width,
                         aDestSize.height,
                         aData.mYStride,
                         aData.mCbCrStride,
                         aStride,
                         yuvtype,
-                        ROTATE_0,
                         FILTER_BILINEAR);
   } else { // no prescale
 #if defined(HAVE_YCBCR_TO_RGB565)
     if (aDestFormat == SurfaceFormat::R5G6B5_UINT16) {
       ConvertYCbCrToRGB565(aData.mYChannel,
                            aData.mCbChannel,
                            aData.mCrChannel,
                            aDestBuffer,
--- a/gfx/ycbcr/moz.build
+++ b/gfx/ycbcr/moz.build
@@ -4,16 +4,17 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS += [
     'YCbCrUtils.h',
 ]
 
 UNIFIED_SOURCES += [
+    'scale_yuv_argb.cpp',
     'ycbcr_to_rgb565.cpp',
     'YCbCrUtils.cpp',
     'yuv_convert.cpp',
     'yuv_row_c.cpp',
     'yuv_row_table.cpp',
 ]
 
 if CONFIG['INTEL_ARCHITECTURE']:
new file mode 100644
--- /dev/null
+++ b/gfx/ycbcr/scale_yuv_argb.cpp
@@ -0,0 +1,1105 @@
+/*
+ *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
+ *  Copyright 2016 Mozilla Foundation
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE 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.
+ */
+
+#include "libyuv/scale.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "libyuv/cpu_id.h"
+#include "libyuv/row.h"
+#include "libyuv/scale_row.h"
+#include "libyuv/video_common.h"
+
+#ifdef __cplusplus
+namespace libyuv {
+extern "C" {
+#endif
+
+// YUV to RGB conversion and scaling functions were implemented by referencing
+// scale_argb.cc
+//
+// libyuv already has ScaleYUVToARGBBilinearUp(), but its implementation is not
+// completed yet. Implementations of the functions are based on it.
+// At first, ScaleYUVToARGBBilinearUp() was implemented by modidying the
+// libyuv's one. Then all another functions were implemented similarly.
+//
+// Function relationship between yuv_convert.cpp abd scale_argb.cc are like
+// the followings
+//  - ScaleYUVToARGBDown2()      <-- ScaleARGBDown2()
+//  - ScaleYUVToARGBDownEven()   <-- ScaleARGBDownEven()
+//  - ScaleYUVToARGBBilinearDown() <-- ScaleARGBBilinearDown()
+//  - ScaleYUVToARGBBilinearUp() <-- ScaleARGBBilinearUp() and ScaleYUVToARGBBilinearUp() in libyuv
+//  - ScaleYUVToARGBSimple()     <-- ScaleARGBSimple()
+//  - ScaleYUVToARGB()           <-- ScaleARGB() // Removed some function calls for simplicity.
+//  - YUVToARGBScale()           <-- ARGBScale()
+//
+// Callings and selections of InterpolateRow() and ScaleARGBFilterCols() were
+// kept as same as possible.
+//
+// The followings changes were done to each scaling functions.
+//
+// -[1] Allocate YUV conversion buffer and use it as source buffer of scaling.
+//      Its usage is borrowed from the libyuv's ScaleYUVToARGBBilinearUp().
+// -[2] Conversion from YUV to RGB was abstracted as YUVBuferIter.
+//      It is for handling multiple yuv color formats.
+// -[3] Modified scaling functions as to handle YUV conversion buffer and
+//      use YUVBuferIter.
+// -[4] Color conversion function selections in YUVBuferIter were borrowed from
+//      I444ToARGBMatrix(), I422ToARGBMatrix() and I420ToARGBMatrix() 
+
+static __inline int Abs(int v) {
+  return v >= 0 ? v : -v;
+}
+
+struct YUVBuferIter {
+  int src_width;
+  int src_height;
+  int src_stride_y;
+  int src_stride_u;
+  int src_stride_v;
+  const uint8* src_y;
+  const uint8* src_u;
+  const uint8* src_v;
+
+  uint32 src_fourcc;
+  int y_index;
+  const uint8* src_row_y;
+  const uint8* src_row_u;
+  const uint8* src_row_v;
+
+  void (*YUVToARGBRow)(const uint8* y_buf,
+                       const uint8* u_buf,
+                       const uint8* v_buf,
+                       uint8* rgb_buf,
+                       const struct YuvConstants* yuvconstants,
+                       int width);
+  void (*MoveTo)(YUVBuferIter& iter, int y_index);
+  void (*MoveToNextRow)(YUVBuferIter& iter);
+};
+
+void YUVBuferIter_InitI422(YUVBuferIter& iter) {
+  iter.YUVToARGBRow = I422ToARGBRow_C;
+#if defined(HAS_I422TOARGBROW_SSSE3)
+  if (TestCpuFlag(kCpuHasSSSE3)) {
+    iter.YUVToARGBRow = I422ToARGBRow_Any_SSSE3;
+    if (IS_ALIGNED(iter.src_width, 8)) {
+      iter.YUVToARGBRow = I422ToARGBRow_SSSE3;
+    }
+  }
+#endif
+#if defined(HAS_I422TOARGBROW_AVX2)
+  if (TestCpuFlag(kCpuHasAVX2)) {
+    iter.YUVToARGBRow = I422ToARGBRow_Any_AVX2;
+    if (IS_ALIGNED(iter.src_width, 16)) {
+      iter.YUVToARGBRow = I422ToARGBRow_AVX2;
+    }
+  }
+#endif
+#if defined(HAS_I422TOARGBROW_NEON)
+  if (TestCpuFlag(kCpuHasNEON)) {
+    iter.YUVToARGBRow = I422ToARGBRow_Any_NEON;
+    if (IS_ALIGNED(iter.src_width, 8)) {
+      iter.YUVToARGBRow = I422ToARGBRow_NEON;
+    }
+  }
+#endif
+#if defined(HAS_I422TOARGBROW_DSPR2)
+  if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(iter.src_width, 4) &&
+      IS_ALIGNED(iter.src_y, 4) && IS_ALIGNED(iter.src_stride_y, 4) &&
+      IS_ALIGNED(iter.src_u, 2) && IS_ALIGNED(iter.src_stride_u, 2) &&
+      IS_ALIGNED(iter.src_v, 2) && IS_ALIGNED(iter.src_stride_v, 2) {
+    // Always satisfy IS_ALIGNED(argb_cnv_row, 4) && IS_ALIGNED(argb_cnv_rowstride, 4)
+    iter.YUVToARGBRow = I422ToARGBRow_DSPR2;
+  }
+#endif
+}
+
+void YUVBuferIter_InitI444(YUVBuferIter& iter) {
+  iter.YUVToARGBRow = I444ToARGBRow_C;
+#if defined(HAS_I444TOARGBROW_SSSE3)
+  if (TestCpuFlag(kCpuHasSSSE3)) {
+    iter.YUVToARGBRow = I444ToARGBRow_Any_SSSE3;
+    if (IS_ALIGNED(iter.src_width, 8)) {
+      iter.YUVToARGBRow = I444ToARGBRow_SSSE3;
+    }
+  }
+#endif
+#if defined(HAS_I444TOARGBROW_AVX2)
+  if (TestCpuFlag(kCpuHasAVX2)) {
+    iter.YUVToARGBRow = I444ToARGBRow_Any_AVX2;
+    if (IS_ALIGNED(iter.src_width, 16)) {
+      iter.YUVToARGBRow = I444ToARGBRow_AVX2;
+    }
+  }
+#endif
+#if defined(HAS_I444TOARGBROW_NEON)
+  if (TestCpuFlag(kCpuHasNEON)) {
+    iter.YUVToARGBRow = I444ToARGBRow_Any_NEON;
+    if (IS_ALIGNED(iter.src_width, 8)) {
+      iter.YUVToARGBRow = I444ToARGBRow_NEON;
+    }
+  }
+#endif
+}
+
+
+static void YUVBuferIter_MoveToForI444(YUVBuferIter& iter, int y_index) {
+  iter.y_index = y_index;
+  iter.src_row_y = iter.src_y + y_index * iter.src_stride_y;
+  iter.src_row_u = iter.src_u + y_index * iter.src_stride_u;
+  iter.src_row_v = iter.src_v + y_index * iter.src_stride_v;
+}
+
+static void YUVBuferIter_MoveToNextRowForI444(YUVBuferIter& iter) {
+  iter.src_row_y += iter.src_stride_y;
+  iter.src_row_u += iter.src_stride_u;
+  iter.src_row_v += iter.src_stride_v;
+  iter.y_index++;
+}
+
+static void YUVBuferIter_MoveToForI422(YUVBuferIter& iter, int y_index) {
+  iter.y_index = y_index;
+  iter.src_row_y = iter.src_y + y_index * iter.src_stride_y;
+  iter.src_row_u = iter.src_u + y_index * iter.src_stride_u;
+  iter.src_row_v = iter.src_v + y_index * iter.src_stride_v;
+}
+
+static void YUVBuferIter_MoveToNextRowForI422(YUVBuferIter& iter) {
+  iter.src_row_y += iter.src_stride_y;
+  iter.src_row_u += iter.src_stride_u;
+  iter.src_row_v += iter.src_stride_v;
+  iter.y_index++;
+}
+
+static void YUVBuferIter_MoveToForI420(YUVBuferIter& iter, int y_index) {
+  const int kYShift = 1;  // Shift Y by 1 to convert Y plane to UV coordinate.
+  int uv_y_index = y_index >> kYShift;
+
+  iter.y_index = y_index;
+  iter.src_row_y = iter.src_y + y_index * iter.src_stride_y;
+  iter.src_row_u = iter.src_u + uv_y_index * iter.src_stride_u;
+  iter.src_row_v = iter.src_v + uv_y_index * iter.src_stride_v;
+}
+
+static void YUVBuferIter_MoveToNextRowForI420(YUVBuferIter& iter) {
+  iter.src_row_y += iter.src_stride_y;
+  if (iter.y_index & 1) {
+    iter.src_row_u += iter.src_stride_u;
+    iter.src_row_v += iter.src_stride_v;
+  }
+  iter.y_index++;
+}
+
+static __inline void YUVBuferIter_ConvertToARGBRow(YUVBuferIter& iter, uint8* argb_row) {
+  iter.YUVToARGBRow(iter.src_row_y, iter.src_row_u, iter.src_row_v, argb_row, &kYuvI601Constants, iter.src_width);
+}
+
+void YUVBuferIter_Init(YUVBuferIter& iter, uint32 src_fourcc) {
+  iter.src_fourcc = src_fourcc;
+  iter.y_index = 0;
+  iter.src_row_y = iter.src_y;
+  iter.src_row_u = iter.src_u;
+  iter.src_row_v = iter.src_v;
+
+  if (src_fourcc == FOURCC_I444) {
+    YUVBuferIter_InitI444(iter);
+    iter.MoveTo = YUVBuferIter_MoveToForI444;
+    iter.MoveToNextRow = YUVBuferIter_MoveToNextRowForI444;
+  } else if(src_fourcc == FOURCC_I422){
+    YUVBuferIter_InitI422(iter);
+    iter.MoveTo = YUVBuferIter_MoveToForI422;
+    iter.MoveToNextRow = YUVBuferIter_MoveToNextRowForI422;
+  } else {
+    assert(src_fourcc == FOURCC_I420); // Should be FOURCC_I420
+    YUVBuferIter_InitI422(iter);
+    iter.MoveTo = YUVBuferIter_MoveToForI420;
+    iter.MoveToNextRow = YUVBuferIter_MoveToNextRowForI420;
+  }
+}
+
+// ScaleARGB ARGB, 1/2
+// This is an optimized version for scaling down a ARGB to 1/2 of
+// its original size.
+static void ScaleYUVToARGBDown2(int src_width, int src_height,
+                                int dst_width, int dst_height,
+                                int src_stride_y,
+                                int src_stride_u,
+                                int src_stride_v,
+                                int dst_stride_argb,
+                                const uint8* src_y,
+                                const uint8* src_u,
+                                const uint8* src_v,
+                                uint8* dst_argb,
+                                int x, int dx, int y, int dy,
+                                enum FilterMode filtering,
+                                uint32 src_fourcc) {
+  int j;
+
+  // Allocate 2 rows of ARGB for source conversion.
+  const int kRowSize = (src_width * 4 + 15) & ~15;
+  align_buffer_64(argb_cnv_row, kRowSize * 2);
+  uint8* argb_cnv_rowptr = argb_cnv_row;
+  int argb_cnv_rowstride = kRowSize;
+
+  YUVBuferIter iter;
+  iter.src_width = src_width;
+  iter.src_height = src_height;
+  iter.src_stride_y = src_stride_y;
+  iter.src_stride_u = src_stride_u;
+  iter.src_stride_v = src_stride_v;
+  iter.src_y = src_y;
+  iter.src_u = src_u;
+  iter.src_v = src_v;
+  YUVBuferIter_Init(iter, src_fourcc);
+
+  void (*ScaleARGBRowDown2)(const uint8* src_argb, ptrdiff_t src_stride,
+                            uint8* dst_argb, int dst_width) =
+    filtering == kFilterNone ? ScaleARGBRowDown2_C :
+        (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_C :
+        ScaleARGBRowDown2Box_C);
+  assert(dx == 65536 * 2);  // Test scale factor of 2.
+  assert((dy & 0x1ffff) == 0);  // Test vertical scale is multiple of 2.
+  // Advance to odd row, even column.
+  int yi = y >> 16;
+  iter.MoveTo(iter, yi);
+  ptrdiff_t x_offset;
+  if (filtering == kFilterBilinear) {
+    x_offset = (x >> 16) * 4;
+  } else {
+    x_offset = ((x >> 16) - 1) * 4;
+  }
+#if defined(HAS_SCALEARGBROWDOWN2_SSE2)
+  if (TestCpuFlag(kCpuHasSSE2)) {
+    ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_Any_SSE2 :
+        (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_Any_SSE2 :
+        ScaleARGBRowDown2Box_Any_SSE2);
+    if (IS_ALIGNED(dst_width, 4)) {
+      ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_SSE2 :
+          (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_SSE2 :
+          ScaleARGBRowDown2Box_SSE2);
+    }
+  }
+
+#endif
+#if defined(HAS_SCALEARGBROWDOWN2_NEON)
+  if (TestCpuFlag(kCpuHasNEON)) {
+    ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_Any_NEON :
+        (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_Any_NEON :
+        ScaleARGBRowDown2Box_Any_NEON);
+    if (IS_ALIGNED(dst_width, 8)) {
+      ScaleARGBRowDown2 = filtering == kFilterNone ? ScaleARGBRowDown2_NEON :
+          (filtering == kFilterLinear ? ScaleARGBRowDown2Linear_NEON :
+          ScaleARGBRowDown2Box_NEON);
+    }
+  }
+#endif
+
+  const int dyi = dy >> 16;
+  int lastyi = yi;
+  YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr);
+  // Prepare next row if necessary
+  if (filtering != kFilterLinear) {
+    if ((yi + dyi) < (src_height - 1)) {
+      iter.MoveTo(iter, yi + dyi);
+      YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr + argb_cnv_rowstride);
+    } else {
+      argb_cnv_rowstride = 0;
+    }
+  }
+
+  if (filtering == kFilterLinear) {
+    argb_cnv_rowstride = 0;
+  }
+  const int max_yi = src_height - 1;
+  const int max_yi_minus_dyi = max_yi - dyi;
+  for (j = 0; j < dst_height; ++j) {
+    if (yi != lastyi) {
+      if (yi > max_yi) {
+        yi = max_yi;
+      }
+      if (yi != lastyi) {
+        if (filtering == kFilterLinear) {
+          iter.MoveTo(iter, yi);
+          YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr);
+          lastyi = yi;
+        } else {
+          // Prepare current row
+          if (yi == iter.y_index) {
+            argb_cnv_rowptr = argb_cnv_rowptr + argb_cnv_rowstride;
+            argb_cnv_rowstride = - argb_cnv_rowstride;
+          } else {
+            iter.MoveTo(iter, yi);
+            argb_cnv_rowptr = argb_cnv_row;
+            argb_cnv_rowstride = kRowSize;
+            YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr);
+          }
+          // Prepare next row if necessary
+          if (iter.y_index  < max_yi) {
+            int next_yi = yi < max_yi_minus_dyi ? yi + dyi : max_yi;
+            iter.MoveTo(iter, next_yi);
+            YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr + argb_cnv_rowstride);
+          } else {
+            argb_cnv_rowstride = 0;
+          }
+          lastyi = yi;
+        }
+      }
+    }
+    ScaleARGBRowDown2(argb_cnv_rowptr + x_offset, argb_cnv_rowstride, dst_argb, dst_width);
+    dst_argb += dst_stride_argb;
+    yi += dyi;
+  }
+
+  free_aligned_buffer_64(argb_cnv_row);
+}
+
+// ScaleARGB ARGB Even
+// This is an optimized version for scaling down a ARGB to even
+// multiple of its original size.
+static void ScaleYUVToARGBDownEven(int src_width, int src_height,
+                                   int dst_width, int dst_height,
+                                   int src_stride_y,
+                                   int src_stride_u,
+                                   int src_stride_v,
+                                   int dst_stride_argb,
+                                   const uint8* src_y,
+                                   const uint8* src_u,
+                                   const uint8* src_v,
+                                   uint8* dst_argb,
+                                   int x, int dx, int y, int dy,
+                                   enum FilterMode filtering,
+                                   uint32 src_fourcc) {
+  int j;
+  // Allocate 2 rows of ARGB for source conversion.
+  const int kRowSize = (src_width * 4 + 15) & ~15;
+  align_buffer_64(argb_cnv_row, kRowSize * 2);
+  uint8* argb_cnv_rowptr = argb_cnv_row;
+  int argb_cnv_rowstride = kRowSize;
+
+  int col_step = dx >> 16;
+  void (*ScaleARGBRowDownEven)(const uint8* src_argb, ptrdiff_t src_stride,
+                               int src_step, uint8* dst_argb, int dst_width) =
+      filtering ? ScaleARGBRowDownEvenBox_C : ScaleARGBRowDownEven_C;
+  assert(IS_ALIGNED(src_width, 2));
+  assert(IS_ALIGNED(src_height, 2));
+  int yi = y >> 16;
+  const ptrdiff_t x_offset = (x >> 16) * 4;
+
+#if defined(HAS_SCALEARGBROWDOWNEVEN_SSE2)
+  if (TestCpuFlag(kCpuHasSSE2)) {
+    ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_Any_SSE2 :
+        ScaleARGBRowDownEven_Any_SSE2;
+    if (IS_ALIGNED(dst_width, 4)) {
+      ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_SSE2 :
+          ScaleARGBRowDownEven_SSE2;
+    }
+  }
+#endif
+#if defined(HAS_SCALEARGBROWDOWNEVEN_NEON)
+  if (TestCpuFlag(kCpuHasNEON)) {
+    ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_Any_NEON :
+        ScaleARGBRowDownEven_Any_NEON;
+    if (IS_ALIGNED(dst_width, 4)) {
+      ScaleARGBRowDownEven = filtering ? ScaleARGBRowDownEvenBox_NEON :
+          ScaleARGBRowDownEven_NEON;
+    }
+  }
+#endif
+
+  YUVBuferIter iter;
+  iter.src_width = src_width;
+  iter.src_height = src_height;
+  iter.src_stride_y = src_stride_y;
+  iter.src_stride_u = src_stride_u;
+  iter.src_stride_v = src_stride_v;
+  iter.src_y = src_y;
+  iter.src_u = src_u;
+  iter.src_v = src_v;
+  YUVBuferIter_Init(iter, src_fourcc);
+
+  const int dyi = dy >> 16;
+  int lastyi = yi;
+  YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr);
+  // Prepare next row if necessary
+  if (filtering != kFilterLinear) {
+    if ((yi + dyi) < (src_height - 1)) {
+      iter.MoveTo(iter, yi + dyi);
+      YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr + argb_cnv_rowstride);
+    } else {
+      argb_cnv_rowstride = 0;
+    }
+  }
+
+  if (filtering == kFilterLinear) {
+    argb_cnv_rowstride = 0;
+  }
+  const int max_yi = src_height - 1;
+  const int max_yi_minus_dyi = max_yi - dyi;
+  for (j = 0; j < dst_height; ++j) {
+    if (yi != lastyi) {
+      if (yi > max_yi) {
+        yi = max_yi;
+      }
+      if (yi != lastyi) {
+        if (filtering == kFilterLinear) {
+          iter.MoveTo(iter, yi);
+          YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr);
+          lastyi = yi;
+        } else {
+          // Prepare current row
+          if (yi == iter.y_index) {
+            argb_cnv_rowptr = argb_cnv_rowptr + argb_cnv_rowstride;
+            argb_cnv_rowstride = - argb_cnv_rowstride;
+          } else {
+            iter.MoveTo(iter, yi);
+            argb_cnv_rowptr = argb_cnv_row;
+            argb_cnv_rowstride = kRowSize;
+            YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr);
+          }
+          // Prepare next row if necessary
+          if (iter.y_index  < max_yi) {
+            int next_yi = yi < max_yi_minus_dyi ? yi + dyi : max_yi;
+            iter.MoveTo(iter, next_yi);
+            YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr + argb_cnv_rowstride);
+          } else {
+            argb_cnv_rowstride = 0;
+          }
+          lastyi = yi;
+        }
+      }
+    }
+    ScaleARGBRowDownEven(argb_cnv_rowptr + x_offset, argb_cnv_rowstride, col_step, dst_argb, dst_width);
+    dst_argb += dst_stride_argb;
+    yi += dyi;
+  }
+  free_aligned_buffer_64(argb_cnv_row);
+}
+
+// Scale YUV to ARGB down with bilinear interpolation.
+static void ScaleYUVToARGBBilinearDown(int src_width, int src_height,
+                                       int dst_width, int dst_height,
+                                       int src_stride_y,
+                                       int src_stride_u,
+                                       int src_stride_v,
+                                       int dst_stride_argb,
+                                       const uint8* src_y,
+                                       const uint8* src_u,
+                                       const uint8* src_v,
+                                       uint8* dst_argb,
+                                       int x, int dx, int y, int dy,
+                                       enum FilterMode filtering,
+                                       uint32 src_fourcc) {
+  int j;
+  void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
+      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
+      InterpolateRow_C;
+  void (*ScaleARGBFilterCols)(uint8* dst_argb, const uint8* src_argb,
+      int dst_width, int x, int dx) =
+      (src_width >= 32768) ? ScaleARGBFilterCols64_C : ScaleARGBFilterCols_C;
+  int64 xlast = x + (int64)(dst_width - 1) * dx;
+  int64 xl = (dx >= 0) ? x : xlast;
+  int64 xr = (dx >= 0) ? xlast : x;
+  int clip_src_width;
+  xl = (xl >> 16) & ~3;  // Left edge aligned.
+  xr = (xr >> 16) + 1;  // Right most pixel used.  Bilinear uses 2 pixels.
+  xr = (xr + 1 + 3) & ~3;  // 1 beyond 4 pixel aligned right most pixel.
+  if (xr > src_width) {
+    xr = src_width;
+  }
+  clip_src_width = (int)(xr - xl) * 4;  // Width aligned to 4.
+  const ptrdiff_t xl_offset = xl * 4;
+  x -= (int)(xl << 16);
+
+  // Allocate 2 row of ARGB for source conversion.
+  const int kRowSize = (src_width * 4 + 15) & ~15;
+  align_buffer_64(argb_cnv_row, kRowSize * 2);
+  uint8* argb_cnv_rowptr = argb_cnv_row; 
+  int argb_cnv_rowstride = kRowSize;
+
+#if defined(HAS_INTERPOLATEROW_SSSE3)
+  if (TestCpuFlag(kCpuHasSSSE3)) {
+    InterpolateRow = InterpolateRow_Any_SSSE3;
+    if (IS_ALIGNED(clip_src_width, 16)) {
+      InterpolateRow = InterpolateRow_SSSE3;
+    }
+  }
+#endif
+#if defined(HAS_INTERPOLATEROW_AVX2)
+  if (TestCpuFlag(kCpuHasAVX2)) {
+    InterpolateRow = InterpolateRow_Any_AVX2;
+    if (IS_ALIGNED(clip_src_width, 32)) {
+      InterpolateRow = InterpolateRow_AVX2;
+    }
+  }
+#endif
+#if defined(HAS_INTERPOLATEROW_NEON)
+  if (TestCpuFlag(kCpuHasNEON)) {
+    InterpolateRow = InterpolateRow_Any_NEON;
+    if (IS_ALIGNED(clip_src_width, 16)) {
+      InterpolateRow = InterpolateRow_NEON;
+    }
+  }
+#endif
+#if defined(HAS_INTERPOLATEROW_DSPR2)
+  if (TestCpuFlag(kCpuHasDSPR2) &&
+      IS_ALIGNED(src_argb, 4) && IS_ALIGNED(argb_cnv_rowstride, 4)) {
+    InterpolateRow = InterpolateRow_Any_DSPR2;
+    if (IS_ALIGNED(clip_src_width, 4)) {
+      InterpolateRow = InterpolateRow_DSPR2;
+    }
+  }
+#endif
+#if defined(HAS_SCALEARGBFILTERCOLS_SSSE3)
+  if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
+    ScaleARGBFilterCols = ScaleARGBFilterCols_SSSE3;
+  }
+#endif
+#if defined(HAS_SCALEARGBFILTERCOLS_NEON)
+  if (TestCpuFlag(kCpuHasNEON)) {
+    ScaleARGBFilterCols = ScaleARGBFilterCols_Any_NEON;
+    if (IS_ALIGNED(dst_width, 4)) {
+      ScaleARGBFilterCols = ScaleARGBFilterCols_NEON;
+    }
+  }
+#endif
+
+  int yi = y >> 16;
+
+  YUVBuferIter iter;
+  iter.src_width = src_width;
+  iter.src_height = src_height;
+  iter.src_stride_y = src_stride_y;
+  iter.src_stride_u = src_stride_u;
+  iter.src_stride_v = src_stride_v;
+  iter.src_y = src_y;
+  iter.src_u = src_u;
+  iter.src_v = src_v;
+  YUVBuferIter_Init(iter, src_fourcc);
+  iter.MoveTo(iter, yi);
+
+  // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
+  // Allocate a row of ARGB.
+  align_buffer_64(row, clip_src_width * 4);
+
+  int lastyi = yi;
+  YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr);
+  // Prepare next row if necessary
+  if (filtering != kFilterLinear) {
+    if ((yi + 1) < src_height) {
+      iter.MoveToNextRow(iter);
+      YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr + argb_cnv_rowstride);
+    } else {
+      argb_cnv_rowstride = 0;
+    }
+  }
+
+  const int max_y = (src_height - 1) << 16;
+  const int max_yi = src_height - 1;
+  for (j = 0; j < dst_height; ++j) {
+    yi = y >> 16;
+    if (yi != lastyi) {
+      if (y > max_y) {
+        y = max_y;
+        yi = y >> 16;
+      }
+      if (yi != lastyi) {
+        if (filtering == kFilterLinear) {
+          iter.MoveTo(iter, yi);
+          YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr);
+          lastyi = yi;
+        } else {
+          // Prepare current row
+          if (yi == iter.y_index) {
+            argb_cnv_rowptr = argb_cnv_rowptr + argb_cnv_rowstride;
+            argb_cnv_rowstride = - argb_cnv_rowstride;
+          } else {
+            iter.MoveTo(iter, yi);
+            argb_cnv_rowptr = argb_cnv_row;
+            argb_cnv_rowstride = kRowSize;
+            YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr);
+          }
+          // Prepare next row if necessary
+          if (iter.y_index < max_yi) {
+            iter.MoveToNextRow(iter);
+            YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_rowptr + argb_cnv_rowstride);
+          } else {
+            argb_cnv_rowstride = 0;
+          }
+          lastyi = yi;
+        }
+      }
+    }
+    if (filtering == kFilterLinear) {
+      ScaleARGBFilterCols(dst_argb, argb_cnv_rowptr + xl_offset, dst_width, x, dx);
+    } else {
+      int yf = (y >> 8) & 255;
+      InterpolateRow(row, argb_cnv_rowptr + xl_offset, argb_cnv_rowstride, clip_src_width, yf);
+      ScaleARGBFilterCols(dst_argb, row, dst_width, x, dx);
+    }
+    dst_argb += dst_stride_argb;
+    y += dy;
+  }
+  free_aligned_buffer_64(row);
+  free_aligned_buffer_64(argb_cnv_row);
+}
+
+// Scale YUV to ARGB up with bilinear interpolation.
+static void ScaleYUVToARGBBilinearUp(int src_width, int src_height,
+                                     int dst_width, int dst_height,
+                                     int src_stride_y,
+                                     int src_stride_u,
+                                     int src_stride_v,
+                                     int dst_stride_argb,
+                                     const uint8* src_y,
+                                     const uint8* src_u,
+                                     const uint8* src_v,
+                                     uint8* dst_argb,
+                                     int x, int dx, int y, int dy,
+                                     enum FilterMode filtering,
+                                     uint32 src_fourcc) {
+  int j;
+  void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
+      ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
+      InterpolateRow_C;
+  void (*ScaleARGBFilterCols)(uint8* dst_argb, const uint8* src_argb,
+      int dst_width, int x, int dx) =
+      filtering ? ScaleARGBFilterCols_C : ScaleARGBCols_C;
+  const int max_y = (src_height - 1) << 16;
+
+  // Allocate 1 row of ARGB for source conversion.
+  align_buffer_64(argb_cnv_row, src_width * 4);
+
+#if defined(HAS_INTERPOLATEROW_SSSE3)
+  if (TestCpuFlag(kCpuHasSSSE3)) {
+    InterpolateRow = InterpolateRow_Any_SSSE3;
+    if (IS_ALIGNED(dst_width, 4)) {
+      InterpolateRow = InterpolateRow_SSSE3;
+    }
+  }
+#endif
+#if defined(HAS_INTERPOLATEROW_AVX2)
+  if (TestCpuFlag(kCpuHasAVX2)) {
+    InterpolateRow = InterpolateRow_Any_AVX2;
+    if (IS_ALIGNED(dst_width, 8)) {
+      InterpolateRow = InterpolateRow_AVX2;
+    }
+  }
+#endif
+#if defined(HAS_INTERPOLATEROW_NEON)
+  if (TestCpuFlag(kCpuHasNEON)) {
+    InterpolateRow = InterpolateRow_Any_NEON;
+    if (IS_ALIGNED(dst_width, 4)) {
+      InterpolateRow = InterpolateRow_NEON;
+    }
+  }
+#endif
+#if defined(HAS_INTERPOLATEROW_DSPR2)
+  if (TestCpuFlag(kCpuHasDSPR2) &&
+      IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
+    InterpolateRow = InterpolateRow_DSPR2;
+  }
+#endif
+  if (src_width >= 32768) {
+    ScaleARGBFilterCols = filtering ?
+        ScaleARGBFilterCols64_C : ScaleARGBCols64_C;
+  }
+#if defined(HAS_SCALEARGBFILTERCOLS_SSSE3)
+  if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
+    ScaleARGBFilterCols = ScaleARGBFilterCols_SSSE3;
+  }
+#endif
+#if defined(HAS_SCALEARGBFILTERCOLS_NEON)
+  if (filtering && TestCpuFlag(kCpuHasNEON)) {
+    ScaleARGBFilterCols = ScaleARGBFilterCols_Any_NEON;
+    if (IS_ALIGNED(dst_width, 4)) {
+      ScaleARGBFilterCols = ScaleARGBFilterCols_NEON;
+    }
+  }
+#endif
+#if defined(HAS_SCALEARGBCOLS_SSE2)
+  if (!filtering && TestCpuFlag(kCpuHasSSE2) && src_width < 32768) {
+    ScaleARGBFilterCols = ScaleARGBCols_SSE2;
+  }
+#endif
+#if defined(HAS_SCALEARGBCOLS_NEON)
+  if (!filtering && TestCpuFlag(kCpuHasNEON)) {
+    ScaleARGBFilterCols = ScaleARGBCols_Any_NEON;
+    if (IS_ALIGNED(dst_width, 8)) {
+      ScaleARGBFilterCols = ScaleARGBCols_NEON;
+    }
+  }
+#endif
+  if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
+    ScaleARGBFilterCols = ScaleARGBColsUp2_C;
+#if defined(HAS_SCALEARGBCOLSUP2_SSE2)
+    if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
+      ScaleARGBFilterCols = ScaleARGBColsUp2_SSE2;
+    }
+#endif
+  }
+
+  if (y > max_y) {
+    y = max_y;
+  }
+
+  int yi = y >> 16;
+
+  YUVBuferIter iter;
+  iter.src_width = src_width;
+  iter.src_height = src_height;
+  iter.src_stride_y = src_stride_y;
+  iter.src_stride_u = src_stride_u;
+  iter.src_stride_v = src_stride_v;
+  iter.src_y = src_y;
+  iter.src_u = src_u;
+  iter.src_v = src_v;
+  YUVBuferIter_Init(iter, src_fourcc);
+  iter.MoveTo(iter, yi);
+
+  // Allocate 2 rows of ARGB.
+  const int kRowSize = (dst_width * 4 + 15) & ~15;
+  align_buffer_64(row, kRowSize * 2);
+
+  uint8* rowptr = row;
+  int rowstride = kRowSize;
+  int lastyi = yi;
+
+  YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_row);
+  ScaleARGBFilterCols(rowptr, argb_cnv_row, dst_width, x, dx);
+
+  if (filtering == kFilterLinear) {
+    rowstride = 0;
+  }
+  // Prepare next row if necessary
+  if (filtering != kFilterLinear) {
+    if ((yi + 1) < src_height) {
+      iter.MoveToNextRow(iter);
+      YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_row);
+      ScaleARGBFilterCols(rowptr + rowstride, argb_cnv_row, dst_width, x, dx);
+    }else {
+      rowstride = 0;
+    }
+  }
+
+  const int max_yi = src_height - 1;
+  for (j = 0; j < dst_height; ++j) {
+    yi = y >> 16;
+    if (yi != lastyi) {
+      if (y > max_y) {
+        y = max_y;
+        yi = y >> 16;
+      }
+      if (yi != lastyi) {
+        if (filtering == kFilterLinear) {
+            iter.MoveToNextRow(iter);
+            YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_row);
+            ScaleARGBFilterCols(rowptr, argb_cnv_row, dst_width, x, dx);
+        } else {
+          // Prepare next row if necessary
+          if (yi < max_yi) {
+            iter.MoveToNextRow(iter);
+            rowptr += rowstride;
+            rowstride = -rowstride;
+            // TODO(fbarchard): Convert the clipped region of row.
+            YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_row);
+            ScaleARGBFilterCols(rowptr + rowstride, argb_cnv_row, dst_width, x, dx);
+          } else {
+            rowstride = 0;
+          }
+        }
+        lastyi = yi;
+      }
+    }
+    if (filtering == kFilterLinear) {
+      InterpolateRow(dst_argb, rowptr, 0, dst_width * 4, 0);
+    } else {
+      int yf = (y >> 8) & 255;
+      InterpolateRow(dst_argb, rowptr, rowstride, dst_width * 4, yf);
+    }
+    dst_argb += dst_stride_argb;
+    y += dy;
+  }
+  free_aligned_buffer_64(row);
+  free_aligned_buffer_64(argb_cnv_row);
+}
+
+// Scale ARGB to/from any dimensions, without interpolation.
+// Fixed point math is used for performance: The upper 16 bits
+// of x and dx is the integer part of the source position and
+// the lower 16 bits are the fixed decimal part.
+
+static void ScaleYUVToARGBSimple(int src_width, int src_height,
+                                 int dst_width, int dst_height,
+                                 int src_stride_y,
+                                 int src_stride_u,
+                                 int src_stride_v,
+                                 int dst_stride_argb,
+                                 const uint8* src_y,
+                                 const uint8* src_u,
+                                 const uint8* src_v,
+                                 uint8* dst_argb,
+                                 int x, int dx, int y, int dy,
+                                 uint32 src_fourcc) {
+  int j;
+  void (*ScaleARGBCols)(uint8* dst_argb, const uint8* src_argb,
+      int dst_width, int x, int dx) =
+      (src_width >= 32768) ? ScaleARGBCols64_C : ScaleARGBCols_C;
+
+  // Allocate 1 row of ARGB for source conversion.
+  align_buffer_64(argb_cnv_row, src_width * 4);
+
+#if defined(HAS_SCALEARGBCOLS_SSE2)
+  if (TestCpuFlag(kCpuHasSSE2) && src_width < 32768) {
+    ScaleARGBCols = ScaleARGBCols_SSE2;
+  }
+#endif
+#if defined(HAS_SCALEARGBCOLS_NEON)
+  if (TestCpuFlag(kCpuHasNEON)) {
+    ScaleARGBCols = ScaleARGBCols_Any_NEON;
+    if (IS_ALIGNED(dst_width, 8)) {
+      ScaleARGBCols = ScaleARGBCols_NEON;
+    }
+  }
+#endif
+  if (src_width * 2 == dst_width && x < 0x8000) {
+    ScaleARGBCols = ScaleARGBColsUp2_C;
+#if defined(HAS_SCALEARGBCOLSUP2_SSE2)
+    if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
+      ScaleARGBCols = ScaleARGBColsUp2_SSE2;
+    }
+#endif
+  }
+
+  int yi = y >> 16;
+
+  YUVBuferIter iter;
+  iter.src_width = src_width;
+  iter.src_height = src_height;
+  iter.src_stride_y = src_stride_y;
+  iter.src_stride_u = src_stride_u;
+  iter.src_stride_v = src_stride_v;
+  iter.src_y = src_y;
+  iter.src_u = src_u;
+  iter.src_v = src_v;
+  YUVBuferIter_Init(iter, src_fourcc);
+  iter.MoveTo(iter, yi);
+
+  int lasty = yi;
+  YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_row);
+
+  for (j = 0; j < dst_height; ++j) {
+    yi = y >> 16;
+    if (yi != lasty) {
+      iter.MoveTo(iter, yi);
+      YUVBuferIter_ConvertToARGBRow(iter, argb_cnv_row);
+      lasty = yi;
+    }
+    ScaleARGBCols(dst_argb, argb_cnv_row, dst_width, x, dx);
+    dst_argb += dst_stride_argb;
+    y += dy;
+  }
+  free_aligned_buffer_64(argb_cnv_row);
+}
+
+static void YUVToARGBCopy(const uint8* src_y, int src_stride_y,
+                          const uint8* src_u, int src_stride_u,
+                          const uint8* src_v, int src_stride_v,
+                          int src_width, int src_height,
+                          uint8* dst_argb, int dst_stride_argb,
+                          int dst_width, int dst_height,
+                          uint32 src_fourcc)
+{
+  YUVBuferIter iter;
+  iter.src_width = src_width;
+  iter.src_height = src_height;
+  iter.src_stride_y = src_stride_y;
+  iter.src_stride_u = src_stride_u;
+  iter.src_stride_v = src_stride_v;
+  iter.src_y = src_y;
+  iter.src_u = src_u;
+  iter.src_v = src_v;
+  YUVBuferIter_Init(iter, src_fourcc);
+
+  for (int j = 0; j < dst_height; ++j) {
+    YUVBuferIter_ConvertToARGBRow(iter, dst_argb);
+    iter.MoveToNextRow(iter);
+    dst_argb += dst_stride_argb;
+  }
+}
+
+static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
+                           const uint8* src_u, int src_stride_u,
+                           const uint8* src_v, int src_stride_v,
+                           int src_width, int src_height,
+                           uint8* dst_argb, int dst_stride_argb,
+                           int dst_width, int dst_height,
+                           enum FilterMode filtering,
+                           uint32 src_fourcc)
+{
+  // Initial source x/y coordinate and step values as 16.16 fixed point.
+  int x = 0;
+  int y = 0;
+  int dx = 0;
+  int dy = 0;
+  // ARGB does not support box filter yet, but allow the user to pass it.
+  // Simplify filtering when possible.
+  filtering = ScaleFilterReduce(src_width, src_height,
+                                dst_width, dst_height,
+                                filtering);
+  ScaleSlope(src_width, src_height, dst_width, dst_height, filtering,
+             &x, &y, &dx, &dy);
+
+  // Special case for integer step values.
+  if (((dx | dy) & 0xffff) == 0) {
+    if (!dx || !dy) {  // 1 pixel wide and/or tall.
+      filtering = kFilterNone;
+    } else {
+      // Optimized even scale down. ie 2, 4, 6, 8, 10x.
+      if (!(dx & 0x10000) && !(dy & 0x10000)) {
+        if (dx == 0x20000) {
+          // Optimized 1/2 downsample.
+          ScaleYUVToARGBDown2(src_width, src_height,
+                              dst_width, dst_height,
+                              src_stride_y,
+                              src_stride_u,
+                              src_stride_v,
+                              dst_stride_argb,
+                              src_y,
+                              src_u,
+                              src_v,
+                              dst_argb,
+                              x, dx, y, dy,
+                              filtering,
+                              src_fourcc);
+          return;
+        }
+        ScaleYUVToARGBDownEven(src_width, src_height,
+                               dst_width, dst_height,
+                               src_stride_y,
+                               src_stride_u,
+                               src_stride_v,
+                               dst_stride_argb,
+                               src_y,
+                               src_u,
+                               src_v,
+                               dst_argb,
+                               x, dx, y, dy,
+                               filtering,
+                               src_fourcc);
+        return;
+      }
+      // Optimized odd scale down. ie 3, 5, 7, 9x.
+      if ((dx & 0x10000) && (dy & 0x10000)) {
+        filtering = kFilterNone;
+        if (dx == 0x10000 && dy == 0x10000) {
+          // Straight conversion and copy.
+          YUVToARGBCopy(src_y, src_stride_y,
+                        src_u, src_stride_u,
+                        src_v, src_stride_v,
+                        src_width, src_height,
+                        dst_argb, dst_stride_argb,
+                        dst_width, dst_height,
+                        src_fourcc);
+          return;
+        }
+      }
+    }
+  }
+  if (filtering && dy < 65536) {
+    ScaleYUVToARGBBilinearUp(src_width, src_height,
+                             dst_width, dst_height,
+                             src_stride_y,
+                             src_stride_u,
+                             src_stride_v,
+                             dst_stride_argb,
+                             src_y,
+                             src_u,
+                             src_v,
+                             dst_argb,
+                             x, dx, y, dy,
+                             filtering,
+                             src_fourcc);
+    return;
+  }
+  if (filtering) {
+    ScaleYUVToARGBBilinearDown(src_width, src_height,
+                               dst_width, dst_height,
+                               src_stride_y,
+                               src_stride_u,
+                               src_stride_v,
+                               dst_stride_argb,
+                               src_y,
+                               src_u,
+                               src_v,
+                               dst_argb,
+                               x, dx, y, dy,
+                               filtering,
+                               src_fourcc);
+    return;
+  }
+  ScaleYUVToARGBSimple(src_width, src_height,
+                       dst_width, dst_height,
+                       src_stride_y,
+                       src_stride_u,
+                       src_stride_v,
+                       dst_stride_argb,
+                       src_y,
+                       src_u,
+                       src_v,
+                       dst_argb,
+                       x, dx, y, dy,
+                       src_fourcc);
+}
+
+bool IsConvertSupported(uint32 src_fourcc)
+{
+  if (src_fourcc == FOURCC_I444 ||
+      src_fourcc == FOURCC_I422 ||
+      src_fourcc == FOURCC_I420) {
+    return true;
+  }
+  return false;
+}
+
+LIBYUV_API
+int YUVToARGBScale(const uint8* src_y, int src_stride_y,
+                   const uint8* src_u, int src_stride_u,
+                   const uint8* src_v, int src_stride_v,
+                   uint32 src_fourcc,
+                   int src_width, int src_height,
+                   uint8* dst_argb, int dst_stride_argb,
+                   int dst_width, int dst_height,
+                   enum FilterMode filtering)
+{
+  if (!src_y || !src_u || !src_v ||
+      src_width == 0 || src_height == 0 ||
+      !dst_argb || dst_width <= 0 || dst_height <= 0) {
+    return -1;
+  }
+  if (!IsConvertSupported(src_fourcc)) {
+    return -1;
+  }
+  ScaleYUVToARGB(src_y, src_stride_y,
+                 src_u, src_stride_u,
+                 src_v, src_stride_v,
+                 src_width, src_height,
+                 dst_argb, dst_stride_argb,
+                 dst_width, dst_height,
+                 filtering,
+                 src_fourcc);
+  return 0;
+}
+
+#ifdef __cplusplus
+}  // extern "C"
+}  // namespace libyuv
+#endif
new file mode 100644
--- /dev/null
+++ b/gfx/ycbcr/scale_yuv_argb.h
@@ -0,0 +1,36 @@
+/*
+ *  Copyright 2012 The LibYuv Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE 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 INCLUDE_LIBYUV_SCALE_YUV_ARGB_H_  // NOLINT
+#define INCLUDE_LIBYUV_SCALE_YUV_ARGB_H_
+
+#include "libyuv/basic_types.h"
+#include "libyuv/scale.h"  // For FilterMode
+
+#ifdef __cplusplus
+namespace libyuv {
+extern "C" {
+#endif
+
+int YUVToARGBScale(const uint8* src_y, int src_stride_y,
+                   const uint8* src_u, int src_stride_u,
+                   const uint8* src_v, int src_stride_v,
+                   uint32 src_fourcc,
+                   int src_width, int src_height,
+                   uint8* dst_argb, int dst_stride_argb,
+                   int dst_width, int dst_height,
+                   enum FilterMode filtering);
+
+#ifdef __cplusplus
+}  // extern "C"
+}  // namespace libyuv
+#endif
+
+#endif  // INCLUDE_LIBYUV_SCALE_YUV_ARGB_H_  NOLINT
--- a/gfx/ycbcr/yuv_convert.cpp
+++ b/gfx/ycbcr/yuv_convert.cpp
@@ -15,45 +15,59 @@
 //
 // ARGB pixel format is output, which on little endian is stored as BGRA.
 // The alpha is set to 255, allowing the application to use RGBA or RGB32.
 
 #include "yuv_convert.h"
 
 #include "gfxPrefs.h"
 #include "libyuv.h"
+#include "scale_yuv_argb.h"
 // Header for low level row functions.
 #include "yuv_row.h"
 #include "mozilla/SSE.h"
 
 namespace mozilla {
 
 namespace gfx {
 
 // 16.16 fixed point arithmetic
 const int kFractionBits = 16;
 const int kFractionMax = 1 << kFractionBits;
 const int kFractionMask = ((1 << kFractionBits) - 1);
 
 YUVType TypeFromSize(int ywidth,
-                              int yheight,
-                              int cbcrwidth,
-                              int cbcrheight)
+                     int yheight,
+                     int cbcrwidth,
+                     int cbcrheight)
 {
   if (ywidth == cbcrwidth && yheight == cbcrheight) {
     return YV24;
   }
   else if ((ywidth + 1) / 2 == cbcrwidth && yheight == cbcrheight) {
     return YV16;
   }
   else {
     return YV12;
   }
 }
 
+libyuv::FourCC FourCCFromYUVType(YUVType aYUVType)
+{
+  if (aYUVType == YV24) {
+    return libyuv::FOURCC_I444;
+  } else if (aYUVType == YV16) {
+    return libyuv::FOURCC_I422;
+  } else if (aYUVType == YV12) {
+    return libyuv::FOURCC_I420;
+  } else {
+    return libyuv::FOURCC_ANY;
+  }
+}
+
 // Convert a frame of YUV to 32 bit ARGB.
 void ConvertYCbCrToRGB32(const uint8* y_buf,
                          const uint8* u_buf,
                          const uint8* v_buf,
                          uint8* rgb_buf,
                          int pic_x,
                          int pic_y,
                          int pic_width,
@@ -238,18 +252,61 @@ void ScaleYCbCrToRGB32(const uint8* y_bu
                        int source_width,
                        int source_height,
                        int width,
                        int height,
                        int y_pitch,
                        int uv_pitch,
                        int rgb_pitch,
                        YUVType yuv_type,
-                       Rotate view_rotate,
                        ScaleFilter filter) {
+
+  bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() ||
+                        (supports_mmx() && supports_sse() && !supports_sse3());
+  if (use_deprecated) {
+    ScaleYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf,
+                                 rgb_buf,
+                                 source_width, source_height,
+                                 width, height,
+                                 y_pitch, uv_pitch,
+                                 rgb_pitch,
+                                 yuv_type,
+                                 ROTATE_0,
+                                 filter);
+    return;
+  }
+
+  DebugOnly<int> err =
+    libyuv::YUVToARGBScale(y_buf, y_pitch,
+                           u_buf, uv_pitch,
+                           v_buf, uv_pitch,
+                           FourCCFromYUVType(yuv_type),
+                           source_width, source_height,
+                           rgb_buf, rgb_pitch,
+                           width, height,
+                           libyuv::kFilterBilinear);
+  MOZ_ASSERT(!err);
+  return;
+}
+
+// Scale a frame of YUV to 32 bit ARGB.
+void ScaleYCbCrToRGB32_deprecated(const uint8* y_buf,
+                                  const uint8* u_buf,
+                                  const uint8* v_buf,
+                                  uint8* rgb_buf,
+                                  int source_width,
+                                  int source_height,
+                                  int width,
+                                  int height,
+                                  int y_pitch,
+                                  int uv_pitch,
+                                  int rgb_pitch,
+                                  YUVType yuv_type,
+                                  Rotate view_rotate,
+                                  ScaleFilter filter) {
   bool has_mmx = supports_mmx();
 
   // 4096 allows 3 buffers to fit in 12k.
   // Helps performance on CPU with 16K L1 cache.
   // Large enough for 3830x2160 and 30" displays which are 2560x1600.
   const int kFilterBufferSize = 4096;
   // Disable filtering if the screen is too big (to avoid buffer overflows).
   // This should never happen to regular users: they don't have monitors
--- a/gfx/ycbcr/yuv_convert.h
+++ b/gfx/ycbcr/yuv_convert.h
@@ -79,15 +79,29 @@ void ScaleYCbCrToRGB32(const uint8* ypla
                        int source_width,
                        int source_height,
                        int width,
                        int height,
                        int ystride,
                        int uvstride,
                        int rgbstride,
                        YUVType yuv_type,
-                       Rotate view_rotate,
                        ScaleFilter filter);
 
+void ScaleYCbCrToRGB32_deprecated(const uint8* yplane,
+                                  const uint8* uplane,
+                                  const uint8* vplane,
+                                  uint8* rgbframe,
+                                  int source_width,
+                                  int source_height,
+                                  int width,
+                                  int height,
+                                  int ystride,
+                                  int uvstride,
+                                  int rgbstride,
+                                  YUVType yuv_type,
+                                  Rotate view_rotate,
+                                  ScaleFilter filter);
+
 } // namespace gfx
 } // namespace mozilla
  
 #endif  // MEDIA_BASE_YUV_CONVERT_H_
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -667,17 +667,17 @@ js::Nursery::collect(JSRuntime* rt, JS::
     endProfile(ProfileKey::Total);
     minorGcCount_++;
 
     int64_t totalTime = profileTimes_[ProfileKey::Total];
     rt->addTelemetry(JS_TELEMETRY_GC_MINOR_US, totalTime);
     rt->addTelemetry(JS_TELEMETRY_GC_MINOR_REASON, reason);
     if (totalTime > 1000)
         rt->addTelemetry(JS_TELEMETRY_GC_MINOR_REASON_LONG, reason);
-    rt->addTelemetry(JS_TELEMETRY_GC_NURSERY_BYTES, nurserySize());
+    rt->addTelemetry(JS_TELEMETRY_GC_NURSERY_BYTES, sizeOfHeapCommitted());
 
     rt->gc.stats.endNurseryCollection(reason);
     TraceMinorGCEnd();
 
     if (enableProfiling_ && totalTime >= profileThreshold_) {
         static int printedHeader = 0;
         if ((printedHeader++ % 200) == 0) {
             fprintf(stderr, "MinorGC:               Reason  PRate Size ");
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -165,16 +165,19 @@ class Nursery
 
     /* Resize an existing object buffer. */
     void* reallocateBuffer(JSObject* obj, void* oldBuffer,
                            uint32_t oldBytes, uint32_t newBytes);
 
     /* Free an object buffer. */
     void freeBuffer(void* buffer);
 
+    /* The maximum number of bytes allowed to reside in nursery buffers. */
+    static const size_t MaxNurseryBufferSize = 1024;
+
     typedef Vector<ObjectGroup*, 0, SystemAllocPolicy> ObjectGroupList;
 
     /*
      * Do a minor collection, optionally specifying a list to store groups which
      * should be pretenured afterwards.
      */
     void collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList* pretenureGroups);
 
@@ -341,19 +344,16 @@ class Nursery
     struct SweepAction;
     SweepAction* sweepActions_;
 
 #ifdef JS_GC_ZEAL
     struct Canary;
     Canary* lastCanary_;
 #endif
 
-    /* The maximum number of bytes allowed to reside in nursery buffers. */
-    static const size_t MaxNurseryBufferSize = 1024;
-
     /* The amount of space in the mapped nursery available to allocations. */
     static const size_t NurseryChunkUsableSize = gc::ChunkSize - sizeof(gc::ChunkTrailer);
 
     struct NurseryChunkLayout {
         char data[NurseryChunkUsableSize];
         gc::ChunkTrailer trailer;
         uintptr_t start() const { return uintptr_t(&data); }
         uintptr_t end() const { return uintptr_t(&trailer); }
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5497,18 +5497,22 @@ GetTemplateObjectForNative(JSContext* cx
             // don't end up with a template whose structure might change later.
             res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, count, TenuredObject));
             if (!res)
                 return false;
             return true;
         }
     }
 
-    if (args.length() == 1 && args[0].isInt32() && args[0].toInt32() >= 0) {
-        uint32_t len = args[0].toInt32();
+    if (args.length() == 1) {
+        size_t len = 0;
+
+        if (args[0].isInt32() && args[0].toInt32() >= 0)
+            len = args[0].toInt32();
+
         if (TypedArrayObject::GetTemplateObjectForNative(cx, native, len, res))
             return !!res;
     }
 
     if (native == js::array_slice) {
         if (args.thisv().isObject()) {
             JSObject* obj = &args.thisv().toObject();
             if (!obj->isSingleton()) {
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -5419,17 +5419,44 @@ CodeGenerator::visitNewTypedArray(LNewTy
 
     OutOfLineCode* ool = oolCallVM(TypedArrayConstructorOneArgInfo, lir,
                                    ArgList(ImmGCPtr(templateObject), Imm32(n)),
                                    StoreRegisterTo(objReg));
 
     masm.createGCObject(objReg, tempReg, templateObject, initialHeap,
                         ool->entry(), /*initContents*/true, /*convertDoubleElements*/false);
 
-    masm.initTypedArraySlots(objReg, tempReg, lengthReg, liveRegs, ool->entry(), ttemplate);
+    masm.initTypedArraySlots(objReg, tempReg, lengthReg, liveRegs, ool->entry(),
+                             ttemplate, TypedArrayLength::Fixed);
+
+    masm.bind(ool->rejoin());
+}
+
+void
+CodeGenerator::visitNewTypedArrayDynamicLength(LNewTypedArrayDynamicLength* lir)
+{
+    Register lengthReg = ToRegister(lir->length());
+    Register objReg = ToRegister(lir->output());
+    Register tempReg = ToRegister(lir->temp());
+    LiveRegisterSet liveRegs = lir->safepoint()->liveRegs();
+
+    JSObject* templateObject = lir->mir()->templateObject();
+    gc::InitialHeap initialHeap = lir->mir()->initialHeap();
+
+    TypedArrayObject* ttemplate = &templateObject->as<TypedArrayObject>();
+
+    OutOfLineCode* ool = oolCallVM(TypedArrayConstructorOneArgInfo, lir,
+                                   ArgList(ImmGCPtr(templateObject), lengthReg),
+                                   StoreRegisterTo(objReg));
+
+    masm.createGCObject(objReg, tempReg, templateObject, initialHeap,
+                        ool->entry(), /*initContents*/true, /*convertDoubleElements*/false);
+
+    masm.initTypedArraySlots(objReg, tempReg, lengthReg, liveRegs, ool->entry(),
+                             ttemplate, TypedArrayLength::Dynamic);
 
     masm.bind(ool->rejoin());
 }
 
 // Out-of-line object allocation for JSOP_NEWOBJECT.
 class OutOfLineNewObject : public OutOfLineCodeBase<CodeGenerator>
 {
     LNewObject* lir_;
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -190,16 +190,17 @@ class CodeGenerator final : public CodeG
     void visitDoubleToInt32(LDoubleToInt32* lir);
     void visitFloat32ToInt32(LFloat32ToInt32* lir);
     void visitNewArrayCallVM(LNewArray* lir);
     void visitNewArray(LNewArray* lir);
     void visitOutOfLineNewArray(OutOfLineNewArray* ool);
     void visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir);
     void visitNewArrayDynamicLength(LNewArrayDynamicLength* lir);
     void visitNewTypedArray(LNewTypedArray* lir);
+    void visitNewTypedArrayDynamicLength(LNewTypedArrayDynamicLength* lir);
     void visitNewObjectVMCall(LNewObject* lir);
     void visitNewObject(LNewObject* lir);
     void visitOutOfLineNewObject(OutOfLineNewObject* ool);
     void visitNewTypedObject(LNewTypedObject* lir);
     void visitSimdBox(LSimdBox* lir);
     void visitSimdUnbox(LSimdUnbox* lir);
     void visitNewDeclEnvObject(LNewDeclEnvObject* lir);
     void visitNewCallObject(LNewCallObject* lir);
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -243,16 +243,27 @@ void
 LIRGenerator::visitNewTypedArray(MNewTypedArray* ins)
 {
     LNewTypedArray* lir = new(alloc()) LNewTypedArray(temp(), temp());
     define(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
+LIRGenerator::visitNewTypedArrayDynamicLength(MNewTypedArrayDynamicLength* ins)
+{
+    MDefinition* length = ins->length();
+    MOZ_ASSERT(length->type() == MIRType::Int32);
+
+    LNewTypedArrayDynamicLength* lir = new(alloc()) LNewTypedArrayDynamicLength(useRegister(length), temp());
+    define(lir, ins);
+    assignSafepoint(lir, ins);
+}
+
+void
 LIRGenerator::visitNewObject(MNewObject* ins)
 {
     LNewObject* lir = new(alloc()) LNewObject(temp());
     define(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -70,16 +70,17 @@ class LIRGenerator : public LIRGenerator
     void visitCallee(MCallee* callee);
     void visitIsConstructing(MIsConstructing* ins);
     void visitGoto(MGoto* ins);
     void visitTableSwitch(MTableSwitch* tableswitch);
     void visitNewArray(MNewArray* ins);
     void visitNewArrayCopyOnWrite(MNewArrayCopyOnWrite* ins);
     void visitNewArrayDynamicLength(MNewArrayDynamicLength* ins);
     void visitNewTypedArray(MNewTypedArray* ins);
+    void visitNewTypedArrayDynamicLength(MNewTypedArrayDynamicLength* ins);
     void visitNewObject(MNewObject* ins);
     void visitNewTypedObject(MNewTypedObject* ins);
     void visitNewDeclEnvObject(MNewDeclEnvObject* ins);
     void visitNewCallObject(MNewCallObject* ins);
     void visitNewSingletonCallObject(MNewSingletonCallObject* ins);
     void visitNewStringObject(MNewStringObject* ins);
     void visitNewDerivedTypedObject(MNewDerivedTypedObject* ins);
     void visitInitElem(MInitElem* ins);
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -2299,50 +2299,55 @@ IonBuilder::inlineTypedArray(CallInfo& c
     if (callInfo.argc() != 1)
         return InliningStatus_NotInlined;
 
     MDefinition* arg = callInfo.getArg(0);
 
     if (arg->type() != MIRType::Int32)
         return InliningStatus_NotInlined;
 
-    if (!arg->maybeConstantValue())
-        return InliningStatus_NotInlined;
-
     JSObject* templateObject = inspector->getTemplateObjectForNative(pc, native);
 
     if (!templateObject) {
         trackOptimizationOutcome(TrackedOutcome::CantInlineNativeNoTemplateObj);
         return InliningStatus_NotInlined;
     }
 
     MOZ_ASSERT(templateObject->is<TypedArrayObject>());
     TypedArrayObject* obj = &templateObject->as<TypedArrayObject>();
 
     // Do not optimize when we see a template object with a singleton type,
     // since it hits at most once.
     if (templateObject->isSingleton())
         return InliningStatus_NotInlined;
 
-    // Negative lengths must throw a RangeError.  (We don't track that this
-    // might have previously thrown, when determining whether to inline, so we
-    // have to deal with this error case when inlining.)
-    int32_t providedLen = arg->maybeConstantValue()->toInt32();
-    if (providedLen < 0)
-        return InliningStatus_NotInlined;
-
-    uint32_t len = AssertedCast<uint32_t>(providedLen);
-
-    if (obj->length() != len)
-        return InliningStatus_NotInlined;
-
-    callInfo.setImplicitlyUsedUnchecked();
-
-    MInstruction* ins = MNewTypedArray::New(alloc(), constraints(), obj,
-                                            obj->group()->initialHeap(constraints()));
+    MInstruction* ins = nullptr;
+
+    if (!arg->isConstant()) {
+        callInfo.setImplicitlyUsedUnchecked();
+        ins = MNewTypedArrayDynamicLength::New(alloc(), constraints(), templateObject,
+                                               templateObject->group()->initialHeap(constraints()),
+                                               arg);
+    } else {
+        // Negative lengths must throw a RangeError.  (We don't track that this
+        // might have previously thrown, when determining whether to inline, so we
+        // have to deal with this error case when inlining.)
+        int32_t providedLen = arg->maybeConstantValue()->toInt32();
+        if (providedLen < 0)
+            return InliningStatus_NotInlined;
+
+        uint32_t len = AssertedCast<uint32_t>(providedLen);
+
+        if (obj->length() != len)
+            return InliningStatus_NotInlined;
+
+        callInfo.setImplicitlyUsedUnchecked();
+        ins = MNewTypedArray::New(alloc(), constraints(), obj,
+                                  obj->group()->initialHeap(constraints()));
+    }
 
     current->add(ins);
     current->push(ins);
     if (!resumeAfter(ins))
         return InliningStatus_Error;
 
     return InliningStatus_Inlined;
 }
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3333,16 +3333,60 @@ class MNewTypedArray : public MNullaryIn
         return initialHeap_;
     }
 
     virtual AliasSet getAliasSet() const override {
         return AliasSet::None();
     }
 };
 
+class MNewTypedArrayDynamicLength
+  : public MUnaryInstruction,
+    public IntPolicy<0>::Data
+{
+    CompilerObject templateObject_;
+    gc::InitialHeap initialHeap_;
+
+    MNewTypedArrayDynamicLength(CompilerConstraintList* constraints, JSObject* templateObject,
+                           gc::InitialHeap initialHeap, MDefinition* length)
+      : MUnaryInstruction(length),
+        templateObject_(templateObject),
+        initialHeap_(initialHeap)
+    {
+        setGuard(); // Need to throw if length is negative.
+        setResultType(MIRType::Object);
+        if (!templateObject->isSingleton())
+            setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject));
+    }
+
+  public:
+    INSTRUCTION_HEADER(NewTypedArrayDynamicLength)
+
+    static MNewTypedArrayDynamicLength* New(TempAllocator& alloc, CompilerConstraintList* constraints,
+                                            JSObject* templateObject, gc::InitialHeap initialHeap,
+                                            MDefinition* length)
+    {
+        return new(alloc) MNewTypedArrayDynamicLength(constraints, templateObject, initialHeap, length);
+    }
+
+    MDefinition* length() const {
+        return getOperand(0);
+    }
+    JSObject* templateObject() const {
+        return templateObject_;
+    }
+    gc::InitialHeap initialHeap() const {
+        return initialHeap_;
+    }
+
+    virtual AliasSet getAliasSet() const override {
+        return AliasSet::None();
+    }
+};
+
 class MNewObject
   : public MUnaryInstruction,
     public NoTypePolicy::Data
 {
   public:
     enum Mode { ObjectLiteral, ObjectCreate };
 
   private:
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -125,16 +125,17 @@ namespace jit {
     _(ExtendInt32ToInt64)                                                   \
     _(Int64ToFloatingPoint)                                                 \
     _(ToString)                                                             \
     _(ToObjectOrNull)                                                       \
     _(NewArray)                                                             \
     _(NewArrayCopyOnWrite)                                                  \
     _(NewArrayDynamicLength)                                                \
     _(NewTypedArray)                                                        \
+    _(NewTypedArrayDynamicLength)                                           \
     _(NewObject)                                                            \
     _(NewTypedObject)                                                       \
     _(NewDeclEnvObject)                                                     \
     _(NewCallObject)                                                        \
     _(NewSingletonCallObject)                                               \
     _(NewStringObject)                                                      \
     _(ObjectState)                                                          \
     _(ArrayState)                                                           \
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1048,42 +1048,61 @@ AllocateObjectBufferWithInit(JSContext* 
             return; \
         break;
 JS_FOR_EACH_TYPED_ARRAY(CREATE_TYPED_ARRAY)
 #undef CREATE_TYPED_ARRAY
       default:
         MOZ_CRASH("Unsupported TypedArray type");
     }
 
-    void* buf = AllocateObjectBuffer<char>(cx, obj, nbytes);
+    nbytes = JS_ROUNDUP(nbytes, sizeof(Value));
+
+    // Elements can only be stored in the nursery since typed arrays have a
+    // finalizer that frees the memory, but the finalizer is only called for
+    // tenured objects. Allocating the memory in the nursery is done to avoid
+    // memory leaks.
+    if (nbytes > Nursery::MaxNurseryBufferSize)
+        return;
+
+    Nursery& nursery = cx->runtime()->gc.nursery;
+    void* buf = nursery.allocateBuffer(obj->zone(), nbytes);
     if (buf) {
-        obj->initPrivate(buf);
-        memset(buf, 0, nbytes);
+        if (nursery.isInside(buf) || obj->isTenured()) {
+            obj->initPrivate(buf);
+            memset(buf, 0, nbytes);
+        } else {
+            // If the nursery is full, |allocateBuffer| will try to allocate
+            // the memory in the tenured heap. This will leak memory when the
+            // object is not tenured since the finalizer will not be called for
+            // non-tenured objects.
+            nursery.removeMallocedBuffer(buf);
+            js_free(buf);
+        }
     }
 }
 
 void
 MacroAssembler::initTypedArraySlots(Register obj, Register temp, Register lengthReg,
                                     LiveRegisterSet liveRegs, Label* fail,
-                                    TypedArrayObject* templateObj)
+                                    TypedArrayObject* templateObj, TypedArrayLength lengthKind)
 {
     MOZ_ASSERT(templateObj->hasPrivate());
     MOZ_ASSERT(!templateObj->hasBuffer());
 
     size_t dataSlotOffset = TypedArrayObject::dataOffset();
     size_t dataOffset = TypedArrayObject::dataOffset() + sizeof(HeapSlot);
 
     static_assert(TypedArrayObject::FIXED_DATA_START == TypedArrayObject::DATA_SLOT + 1,
                     "fixed inline element data assumed to begin after the data slot");
 
     // Initialise data elements to zero.
     int32_t length = templateObj->length();
     size_t nbytes = length * templateObj->bytesPerElement();
 
-    if (dataOffset + nbytes <= JSObject::MAX_BYTE_SIZE) {
+    if (lengthKind == TypedArrayLength::Fixed && dataOffset + nbytes <= JSObject::MAX_BYTE_SIZE) {
         MOZ_ASSERT(dataOffset + nbytes <= templateObj->tenuredSizeOfThis());
 
         // Store data elements inside the remaining JSObject slots.
         computeEffectiveAddress(Address(obj, dataOffset), temp);
         storePtr(temp, Address(obj, dataSlotOffset));
 
         // Write enough zero pointers into fixed data to zero every
         // element.  (This zeroes past the end of a byte count that's
@@ -1092,17 +1111,18 @@ MacroAssembler::initTypedArraySlots(Regi
         // and we won't inline unless the desired memory fits in that
         // space.)
         static_assert(sizeof(HeapSlot) == 8, "Assumed 8 bytes alignment");
 
         size_t numZeroPointers = ((nbytes + 7) & ~0x7) / sizeof(char *);
         for (size_t i = 0; i < numZeroPointers; i++)
             storePtr(ImmWord(0), Address(obj, dataOffset + i * sizeof(char *)));
     } else {
-        move32(Imm32(length), lengthReg);
+        if (lengthKind == TypedArrayLength::Fixed)
+            move32(Imm32(length), lengthReg);
 
         // Allocate a buffer on the heap to store the data elements.
         liveRegs.addUnchecked(temp);
         liveRegs.addUnchecked(obj);
         liveRegs.addUnchecked(lengthReg);
         PushRegsInMask(liveRegs);
         setupUnalignedABICall(temp);
         loadJSContext(temp);
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -30,16 +30,17 @@
 # error "Unknown architecture!"
 #endif
 #include "jit/AtomicOp.h"
 #include "jit/IonInstrumentation.h"
 #include "jit/JitCompartment.h"
 #include "jit/VMFunctions.h"
 #include "vm/ProxyObject.h"
 #include "vm/Shape.h"
+#include "vm/TypedArrayObject.h"
 #include "vm/UnboxedObject.h"
 
 using mozilla::FloatingPoint;
 
 // * How to read/write MacroAssembler method declarations:
 //
 // The following macros are made to avoid #ifdef around each method declarations
 // of the Macro Assembler, and they are also used as an hint on the location of
@@ -1638,17 +1639,17 @@ class MacroAssembler : public MacroAssem
     void createGCObject(Register result, Register temp, JSObject* templateObj,
                         gc::InitialHeap initialHeap, Label* fail, bool initContents = true,
                         bool convertDoubleElements = false);
 
     void initGCThing(Register obj, Register temp, JSObject* templateObj,
                      bool initContents = true, bool convertDoubleElements = false);
     void initTypedArraySlots(Register obj, Register temp, Register lengthReg,
                              LiveRegisterSet liveRegs, Label* fail,
-                             TypedArrayObject* templateObj);
+                             TypedArrayObject* templateObj, TypedArrayLength lengthKind);
 
     void initUnboxedObjectContents(Register object, UnboxedPlainObject* templateObject);
 
     void newGCString(Register result, Register temp, Label* fail);
     void newGCFatInlineString(Register result, Register temp, Label* fail);
 
     // Compares two strings for equality based on the JSOP.
     // This checks for identical pointers, atoms and length and fails for everything else.
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -1080,16 +1080,38 @@ class LNewTypedArray : public LInstructi
         return getTemp(1);
     }
 
     MNewTypedArray* mir() const {
         return mir_->toNewTypedArray();
     }
 };
 
+class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1>
+{
+  public:
+    LIR_HEADER(NewTypedArrayDynamicLength)
+
+    explicit LNewTypedArrayDynamicLength(const LAllocation& length, const LDefinition& temp) {
+        setOperand(0, length);
+        setTemp(0, temp);
+    }
+
+    const LAllocation* length() {
+        return getOperand(0);
+    }
+    const LDefinition* temp() {
+        return getTemp(0);
+    }
+
+    MNewTypedArrayDynamicLength* mir() const {
+        return mir_->toNewTypedArrayDynamicLength();
+    }
+};
+
 class LNewObject : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewObject)
 
     explicit LNewObject(const LDefinition& temp) {
         setTemp(0, temp);
     }
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -63,16 +63,17 @@
     _(IsConstructing)               \
     _(TableSwitch)                  \
     _(TableSwitchV)                 \
     _(Goto)                         \
     _(NewArray)                     \
     _(NewArrayCopyOnWrite)          \
     _(NewArrayDynamicLength)        \
     _(NewTypedArray)                \
+    _(NewTypedArrayDynamicLength)   \
     _(ArraySplice)                  \
     _(NewObject)                    \
     _(NewTypedObject)               \
     _(NewDeclEnvObject)             \
     _(NewCallObject)                \
     _(NewSingletonCallObject)       \
     _(NewStringObject)              \
     _(NewDerivedTypedObject)        \
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -1045,18 +1045,16 @@ if test "$HAVE_64BIT_BUILD" ; then
 else
     AC_DEFINE(JS_NUNBOX32)
 fi
 
 MOZ_ARG_DISABLE_BOOL(ion,
 [  --disable-ion      Disable use of the IonMonkey JIT],
   ENABLE_ION= )
 
-AC_SUBST(ENABLE_METHODJIT_SPEW)
-
 AC_SUBST(ENABLE_ION)
 
 if test -n "$COMPILE_ENVIRONMENT"; then
     MOZ_COMPILER_OPTS
 fi
 
 if test -z "$SKIP_COMPILER_CHECKS"; then
 dnl Checks for typedefs, structures, and compiler characteristics.
@@ -1657,20 +1655,16 @@ MOZ_ARG_HEADER(Individual module options
 
 dnl ========================================================
 dnl =
 dnl = Debugging Options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Debugging and Optimizations)
 
-if test "$ENABLE_METHODJIT_SPEW"; then
-    AC_DEFINE(JS_METHODJIT_SPEW)
-fi
-
 dnl ========================================================
 dnl = Enable code optimization. ON by default.
 dnl ========================================================
 if test -z "$MOZ_OPTIMIZE_FLAGS"; then
 	MOZ_OPTIMIZE_FLAGS="-O"
 fi
 
 MOZ_ARG_ENABLE_STRING(optimize,
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -249,17 +249,17 @@ AllocateArrayBufferContents(JSContext* c
     return ArrayBufferObject::BufferContents::create<ArrayBufferObject::PLAIN>(p);
 }
 
 static void
 NoteViewBufferWasDetached(ArrayBufferViewObject* view,
                           ArrayBufferObject::BufferContents newContents,
                           JSContext* cx)
 {
-    view->notifyBufferDetached(newContents.data());
+    view->notifyBufferDetached(cx, newContents.data());
 
     // Notify compiled jit code that the base pointer has moved.
     MarkObjectStateChange(cx, view);
 }
 
 /* static */ bool
 ArrayBufferObject::detach(JSContext* cx, Handle<ArrayBufferObject*> buffer,
                           BufferContents newContents)
@@ -1074,25 +1074,25 @@ JSObject::is<js::ArrayBufferViewObject>(
 template <>
 bool
 JSObject::is<js::ArrayBufferObjectMaybeShared>() const
 {
     return is<ArrayBufferObject>() || is<SharedArrayBufferObject>();
 }
 
 void
-ArrayBufferViewObject::notifyBufferDetached(void* newData)
+ArrayBufferViewObject::notifyBufferDetached(JSContext* cx, void* newData)
 {
     MOZ_ASSERT(newData != nullptr);
     if (is<DataViewObject>()) {
         as<DataViewObject>().notifyBufferDetached(newData);
     } else if (is<TypedArrayObject>()) {
         if (as<TypedArrayObject>().isSharedMemory())
             return;
-        as<TypedArrayObject>().notifyBufferDetached(newData);
+        as<TypedArrayObject>().notifyBufferDetached(cx, newData);
     } else {
         as<OutlineTypedObject>().notifyBufferDetached(newData);
     }
 }
 
 uint8_t*
 ArrayBufferViewObject::dataPointerUnshared()
 {
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -383,17 +383,17 @@ typedef MutableHandle<ArrayBufferObject*
  * Common definitions shared by all array buffer views.
  */
 
 class ArrayBufferViewObject : public JSObject
 {
   public:
     static ArrayBufferObjectMaybeShared* bufferObject(JSContext* cx, Handle<ArrayBufferViewObject*> obj);
 
-    void notifyBufferDetached(void* newData);
+    void notifyBufferDetached(JSContext* cx, void* newData);
 
 #ifdef DEBUG
     bool isSharedMemory();
 #endif
 
     // By construction we only need unshared variants here.  See
     // comments in ArrayBufferObject.cpp.
     uint8_t* dataPointerUnshared();
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -38,16 +38,17 @@
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/SelfHosting.h"
 #include "vm/TypedArrayCommon.h"
 #include "vm/WrapperObject.h"
 
 #include "jsatominlines.h"
 
+#include "gc/Nursery-inl.h"
 #include "gc/StoreBuffer-inl.h"
 #include "vm/ArrayBufferObject-inl.h"
 #include "vm/NativeObject-inl.h"
 #include "vm/Shape-inl.h"
 
 using namespace js;
 using namespace js::gc;
 
@@ -72,21 +73,29 @@ TypedArrayObject::lengthOffset()
 
 /* static */ int
 TypedArrayObject::dataOffset()
 {
     return NativeObject::getPrivateDataOffset(DATA_SLOT);
 }
 
 void
-TypedArrayObject::notifyBufferDetached(void* newData)
+TypedArrayObject::notifyBufferDetached(JSContext* cx, void* newData)
 {
     MOZ_ASSERT(!isSharedMemory());
     setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(0));
     setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(0));
+
+    // Free the data slot pointer if has no inline data
+    Nursery& nursery = cx->runtime()->gc.nursery;
+    if (!hasBuffer() && !hasInlineElements() && !nursery.isInside(elements())) {
+        nursery.removeMallocedBuffer(elements());
+        js_free(elements());
+    }
+
     setPrivate(newData);
 }
 
 /* static */ bool
 TypedArrayObject::is(HandleValue v)
 {
     return v.isObject() && v.toObject().is<TypedArrayObject>();
 }
@@ -101,16 +110,24 @@ TypedArrayObject::ensureHasBuffer(JSCont
     if (!buffer)
         return false;
 
     if (!buffer->addView(cx, tarray))
         return false;
 
     // tarray is not shared, because if it were it would have a buffer.
     memcpy(buffer->dataPointer(), tarray->viewDataUnshared(), tarray->byteLength());
+
+    // Free the data slot pointer if has no inline data
+    Nursery& nursery = cx->runtime()->gc.nursery;
+    if (!tarray->hasInlineElements() && !nursery.isInside(tarray->elements())) {
+        nursery.removeMallocedBuffer(tarray->elements());
+        js_free(tarray->elements());
+    }
+
     tarray->setPrivate(buffer->dataPointer());
 
     tarray->setFixedSlot(TypedArrayObject::BUFFER_SLOT, ObjectValue(*buffer));
 
     // Notify compiled jit code that the base pointer has moved.
     MarkObjectStateChange(cx, tarray);
 
     return true;
@@ -129,18 +146,18 @@ TypedArrayObject::finalize(FreeOp* fop, 
     MOZ_ASSERT(!IsInsideNursery(obj));
     TypedArrayObject* curObj = &obj->as<TypedArrayObject>();
 
     // Typed arrays with a buffer object do not need to be free'd
     if (curObj->hasBuffer())
         return;
 
     // Free the data slot pointer if it does not point into the old JSObject.
-    if (!curObj->hasInlineElements()) {
-        MOZ_ASSERT(!fop->runtime()->gc.nursery.isInside(curObj->elements()));
+    Nursery& nursery = fop->runtime()->gc.nursery;
+    if (!curObj->hasInlineElements() && !nursery.isInside(curObj->elements())) {
         js_free(curObj->elements());
     }
 }
 
 /* static */ void
 TypedArrayObject::objectMoved(JSObject* obj, const JSObject* old)
 {
     TypedArrayObject* newObj = &obj->as<TypedArrayObject>();
@@ -157,16 +174,17 @@ TypedArrayObject::objectMoved(JSObject* 
 
 /* static */ size_t
 TypedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* obj, const JSObject* old,
                                            gc::AllocKind newAllocKind)
 {
     TypedArrayObject* newObj = &obj->as<TypedArrayObject>();
     const TypedArrayObject* oldObj = &old->as<TypedArrayObject>();
     MOZ_ASSERT(newObj->elements() == oldObj->elements());
+    MOZ_ASSERT(obj->isTenured());
 
     // Typed arrays with a buffer object do not need an update.
     if (oldObj->hasBuffer())
         return 0;
 
     Nursery& nursery = trc->runtime()->gc.nursery;
     void* buf = oldObj->elements();
 
@@ -189,19 +207,21 @@ JS_FOR_EACH_TYPED_ARRAY(OBJECT_MOVED_TYP
       default:
         MOZ_CRASH("Unsupported TypedArray type");
     }
 
     if (dataOffset() + nbytes <= GetGCKindBytes(newAllocKind)) {
         newObj->setInlineElements();
     } else {
         AutoEnterOOMUnsafeRegion oomUnsafe;
-        uint8_t* data = newObj->zone()->pod_malloc<uint8_t>(nbytes);
+        nbytes = JS_ROUNDUP(nbytes, sizeof(Value));
+        void* data = newObj->zone()->pod_malloc<uint8_t>(nbytes);
         if (!data)
             oomUnsafe.crash("Failed to allocate typed array elements while tenuring.");
+        MOZ_ASSERT(!nursery.isInside(data));
         newObj->initPrivate(data);
     }
 
     mozilla::PodCopy(newObj->elements(), oldObj->elements(), nbytes);
 
     // Set a forwarding pointer for the element buffers in case they were
     // preserved on the stack by Ion.
     nursery.maybeSetForwardingPointer(trc, oldObj->elements(), newObj->elements(), true);
@@ -558,97 +578,91 @@ class TypedArrayObjectTemplate : public 
             return nullptr;
         }
 
         TypedArrayObject* tarray = &tmp->as<TypedArrayObject>();
         // Template objects do not need memory for its elements, since there
         // won't be any elements to store. Therefore, we set the pointer to the
         // inline data and avoid allocating memory that will never be used.
         void* buf = tarray->fixedData(FIXED_DATA_START);
-        initTypedArraySlots(tarray, len, buf, allocKind);
+        initTypedArraySlots(cx, tarray, len, buf, allocKind);
 
         return tarray;
     }
 
     static void
-    initTypedArraySlots(TypedArrayObject* tarray, uint32_t len, void* buf,
-                        AllocKind allocKind)
+    initTypedArraySlots(JSContext* cx, TypedArrayObject* tarray, uint32_t len,
+                        void* buf, AllocKind allocKind)
     {
         tarray->setFixedSlot(TypedArrayObject::BUFFER_SLOT, NullValue());
         tarray->setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(AssertedCast<int32_t>(len)));
         tarray->setFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT, Int32Value(0));
 
         // Verify that the private slot is at the expected place.
         MOZ_ASSERT(tarray->numFixedSlots() == TypedArrayObject::DATA_SLOT);
 
         if (buf) {
+#ifdef DEBUG
+            Nursery& nursery = cx->runtime()->gc.nursery;
+            MOZ_ASSERT_IF(!nursery.isInside(buf) && !tarray->hasInlineElements(),
+                          tarray->isTenured());
+#endif
             tarray->initPrivate(buf);
         } else {
             size_t nbytes = len * sizeof(NativeType);
 #ifdef DEBUG
             size_t dataOffset = TypedArrayObject::dataOffset();
             size_t offset = dataOffset + sizeof(HeapSlot);
             MOZ_ASSERT(offset + nbytes <= GetGCKindBytes(allocKind));
 #endif
 
             void* data = tarray->fixedData(FIXED_DATA_START);
             tarray->initPrivate(data);
             memset(data, 0, nbytes);
         }
     }
 
-    static void*
-    allocateTypedArrayElementsBuffer(JSContext* cx, uint32_t len)
-    {
-        if (len == 0)
-            return nullptr;
-
-        void* buf = cx->runtime()->pod_callocCanGC<HeapSlot>(len);
-        if (!buf) {
-            ReportOutOfMemory(cx);
-            return nullptr;
-        }
-        return buf;
-    }
-
     static TypedArrayObject*
     makeTypedArrayWithTemplate(JSContext* cx, TypedArrayObject* templateObj, uint32_t len)
     {
         size_t nbytes;
         if (!js::CalculateAllocSize<NativeType>(len, &nbytes))
             return nullptr;
 
-        MOZ_ASSERT(nbytes < TypedArrayObject::SINGLETON_BYTE_LENGTH);
         bool fitsInline = nbytes <= INLINE_BUFFER_LIMIT;
 
         AutoSetNewObjectMetadata metadata(cx);
 
         const Class* clasp = templateObj->group()->clasp();
         gc::AllocKind allocKind = !fitsInline
                                   ? GetGCObjectKind(clasp)
                                   : AllocKindForLazyBuffer(len * sizeof(NativeType));
         MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, clasp));
         allocKind = GetBackgroundAllocKind(allocKind);
         RootedObjectGroup group(cx, templateObj->group());
 
-        NewObjectKind newKind = GenericObject;
+        NewObjectKind newKind = TenuredObject;
 
         ScopedJSFreePtr<void> buf;
-        if (!fitsInline) {
-            buf = allocateTypedArrayElementsBuffer(cx, len);
-            if (!buf)
+        if (!fitsInline && len > 0) {
+            buf = cx->zone()->pod_malloc<uint8_t>(nbytes);
+            if (!buf) {
+                ReportOutOfMemory(cx);
                 return nullptr;
-        }
+            }
+
+            memset(buf, 0, nbytes);
+         }
 
         RootedObject tmp(cx, NewObjectWithGroup<TypedArrayObject>(cx, group, allocKind, newKind));
         if (!tmp)
             return nullptr;
 
         TypedArrayObject* obj = &tmp->as<TypedArrayObject>();
-        initTypedArraySlots(obj, len, buf.forget(), allocKind);
+        initTypedArraySlots(cx, obj, len, buf.forget(), allocKind);
 
         return obj;
     }
 
     /*
      * new [Type]Array(length)
      * new [Type]Array(otherTypedArray)
      * new [Type]Array(JSArray)
@@ -1246,21 +1260,21 @@ TypedArrayConstructor(JSContext* cx, uns
 /* static */ bool
 TypedArrayObject::GetTemplateObjectForNative(JSContext* cx, Native native, uint32_t len,
                                              MutableHandleObject res)
 {
 #define CHECK_TYPED_ARRAY_CONSTRUCTOR(T, N) \
     if (native == &TypedArrayObjectTemplate<T>::class_constructor) { \
         size_t nbytes; \
         if (!js::CalculateAllocSize<T>(len, &nbytes)) \
-            return false; \
+            return true; \
         \
         if (nbytes < TypedArrayObject::SINGLETON_BYTE_LENGTH) { \
             res.set(TypedArrayObjectTemplate<T>::makeTemplateObject(cx, len)); \
-            return !!res; \
+            return true; \
         } \
     }
 JS_FOR_EACH_TYPED_ARRAY(CHECK_TYPED_ARRAY_CONSTRUCTOR)
 #undef CHECK_TYPED_ARRAY_CONSTRUCTOR
     return false;
 }
 
 /*
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -26,16 +26,18 @@
     macro(float, Float32) \
     macro(double, Float64) \
     macro(uint8_clamped, Uint8Clamped)
 
 typedef struct JSProperty JSProperty;
 
 namespace js {
 
+enum class TypedArrayLength { Fixed, Dynamic };
+
 /*
  * TypedArrayObject
  *
  * The non-templated base class for the specific typed implementations.
  * This class holds all the member variables that are used by
  * the subclasses.
  */
 
@@ -165,17 +167,17 @@ class TypedArrayObject : public NativeOb
     void setInlineElements();
     uint8_t* elements() const {
         return *(uint8_t **)((((char *)this) + this->dataOffset()));
     }
 
     Value getElement(uint32_t index);
     static void setElement(TypedArrayObject& obj, uint32_t index, double d);
 
-    void notifyBufferDetached(void* newData);
+    void notifyBufferDetached(JSContext* cx, void* newData);
 
     static bool
     GetTemplateObjectForNative(JSContext* cx, Native native, uint32_t len,
                                MutableHandleObject res);
 
     /*
      * Byte length above which created typed arrays and data views will have
      * singleton types regardless of the context in which they are created.
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -3696,17 +3696,17 @@ ContainerState::ComputeOpaqueRect(nsDisp
         RelativeTo::ScrollFrame);
     if (!usingDisplayport) {
       // No async scrolling, so all that matters is that the layer contents
       // cover the scrollport.
       displayport = sf->GetScrollPortRect();
     }
     nsIFrame* scrollFrame = do_QueryFrame(sf);
     displayport += scrollFrame->GetOffsetToCrossDoc(mContainerReferenceFrame);
-    if (opaque.Contains(displayport)) {
+    if (opaquePixels.Contains(ScaleRegionToNearestPixels(displayport))) {
       *aOpaqueForAnimatedGeometryRootParent = true;
     }
   }
   return opaquePixels;
 }
 
 static const DisplayItemScrollClip*
 InnermostScrollClipApplicableToAGR(const DisplayItemScrollClip* aItemScrollClip,
@@ -4701,17 +4701,17 @@ FrameLayerBuilder::CheckInLayerTreeCompr
 }
 
 void
 ContainerState::CollectOldLayers()
 {
   for (Layer* layer = mContainerLayer->GetFirstChild(); layer;
        layer = layer->GetNextSibling()) {
     NS_ASSERTION(!layer->HasUserData(&gMaskLayerUserData),
-                 "Mask layer in layer tree; could not be recycled.");
+                 "Mask layers should not be part of the layer tree.");
     if (layer->HasUserData(&gPaintedDisplayItemLayerUserData)) {
       NS_ASSERTION(layer->AsPaintedLayer(), "Wrong layer type");
       mPaintedLayersAvailableForRecycling.PutEntry(static_cast<PaintedLayer*>(layer));
     }
 
     if (Layer* maskLayer = layer->GetMaskLayer()) {
       NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE,
                    "Could not recycle mask layer, unsupported layer type.");
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -165,16 +165,19 @@ typedef nsStyleTransformMatrix::Transfor
 /* static */ uint32_t nsLayoutUtils::sFontSizeInflationMaxRatio;
 /* static */ bool nsLayoutUtils::sFontSizeInflationForceEnabled;
 /* static */ bool nsLayoutUtils::sFontSizeInflationDisabledInMasterProcess;
 /* static */ bool nsLayoutUtils::sInvalidationDebuggingIsEnabled;
 /* static */ bool nsLayoutUtils::sCSSVariablesEnabled;
 /* static */ bool nsLayoutUtils::sInterruptibleReflowEnabled;
 /* static */ bool nsLayoutUtils::sSVGTransformBoxEnabled;
 /* static */ bool nsLayoutUtils::sTextCombineUprightDigitsEnabled;
+#ifdef MOZ_STYLO
+/* static */ bool nsLayoutUtils::sStyloEnabled;
+#endif
 
 static ViewID sScrollIdCounter = FrameMetrics::START_SCROLL_ID;
 
 typedef nsDataHashtable<nsUint64HashKey, nsIContent*> ContentMap;
 static ContentMap* sContentMap = nullptr;
 static ContentMap& GetContentMap() {
   if (!sContentMap) {
     sContentMap = new ContentMap();
@@ -7835,16 +7838,20 @@ nsLayoutUtils::Initialize()
   Preferences::AddBoolVarCache(&sCSSVariablesEnabled,
                                "layout.css.variables.enabled");
   Preferences::AddBoolVarCache(&sInterruptibleReflowEnabled,
                                "layout.interruptible-reflow.enabled");
   Preferences::AddBoolVarCache(&sSVGTransformBoxEnabled,
                                "svg.transform-box.enabled");
   Preferences::AddBoolVarCache(&sTextCombineUprightDigitsEnabled,
                                "layout.css.text-combine-upright-digits.enabled");
+#ifdef MOZ_STYLO
+  Preferences::AddBoolVarCache(&sStyloEnabled,
+                               "layout.css.servo.enabled");
+#endif
 
   for (auto& callback : kPrefCallbacks) {
     Preferences::RegisterCallbackAndCall(callback.func, callback.name);
   }
   nsComputedDOMStyle::RegisterPrefChangeCallbacks();
 }
 
 /* static */
@@ -9332,12 +9339,12 @@ nsLayoutUtils::GetCumulativeApzCallbackT
     content = frame ? frame->GetContent() : nullptr;
   }
   return delta;
 }
 
 /* static */ bool
 nsLayoutUtils::SupportsServoStyleBackend(nsIDocument* aDocument)
 {
-  return nsPresContext::StyloEnabled() &&
+  return StyloEnabled() &&
          aDocument->IsHTMLOrXHTML() &&
          static_cast<nsDocument*>(aDocument)->IsContentDocument();
 }
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -2416,16 +2416,27 @@ public:
   static bool SVGTransformBoxEnabled() {
     return sSVGTransformBoxEnabled;
   }
 
   static bool TextCombineUprightDigitsEnabled() {
     return sTextCombineUprightDigitsEnabled;
   }
 
+  // Stylo (the Servo backend for Gecko's style system) is generally enabled
+  // or disabled at compile-time. However, we provide the additional capability
+  // to disable it dynamically in stylo-enabled builds via a pref.
+  static bool StyloEnabled() {
+#ifdef MOZ_STYLO
+    return sStyloEnabled;
+#else
+    return false;
+#endif
+  }
+
   /**
    * See comment above "font.size.inflation.mappingIntercept" in
    * modules/libpref/src/init/all.js .
    */
   static int32_t FontSizeInflationMappingIntercept() {
     return sFontSizeInflationMappingIntercept;
   }
 
@@ -2856,16 +2867,19 @@ private:
   static uint32_t sFontSizeInflationMaxRatio;
   static bool sFontSizeInflationForceEnabled;
   static bool sFontSizeInflationDisabledInMasterProcess;
   static bool sInvalidationDebuggingIsEnabled;
   static bool sCSSVariablesEnabled;
   static bool sInterruptibleReflowEnabled;
   static bool sSVGTransformBoxEnabled;
   static bool sTextCombineUprightDigitsEnabled;
+#ifdef MOZ_STYLO
+  static bool sStyloEnabled;
+#endif
 
   /**
    * Helper function for LogTestDataForPaint().
    */
   static void DoLogTestDataForPaint(mozilla::layers::LayerManager* aManager,
                                     ViewID aScrollId,
                                     const std::string& aKey,
                                     const std::string& aValue);
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -1101,30 +1101,16 @@ public:
   bool HasWarnedAboutTooLargeDashedOrDottedRadius() const {
     return mHasWarnedAboutTooLargeDashedOrDottedRadius;
   }
 
   void SetHasWarnedAboutTooLargeDashedOrDottedRadius() {
     mHasWarnedAboutTooLargeDashedOrDottedRadius = true;
   }
 
-  static bool StyloEnabled()
-  {
-    // Stylo (the Servo backend for Gecko's style system) is generally enabled
-    // or disabled at compile-time. However, we provide the additional capability
-    // to disable it dynamically in stylo-enabled builds via an environmental
-    // variable.
-#ifdef MOZ_STYLO
-    static bool disabled = PR_GetEnv("MOZ_DISABLE_STYLO");
-    return !disabled;
-#else
-    return false;
-#endif
-  }
-
 protected:
   friend class nsRunnableMethod<nsPresContext>;
   void ThemeChangedInternal();
   void SysColorChangedInternal();
 
   // update device context's resolution from the widget
   void UIResolutionChangedInternal();
 
--- a/layout/base/tests/bug1082486-1.html
+++ b/layout/base/tests/bug1082486-1.html
@@ -6,15 +6,24 @@
      /* Eliminate the blue glow when focusing the element. */
      input {
        background: none;
        border: none;
        outline: none;
      }
      </style>
   </head>
-  <body onload="document.getElementById('i').focus();">
+  <body onload="focusInput();">
+    <script>
+      function focusInput() {
+        var inp = document.getElementById('i');
+        inp.selectionStart = 0;
+        inp.selectionEnd = 0;
+        inp.focus();
+      }
+    </script>
+
     <a target="_blank" href="https://bugzil.la/1082486">Mozilla Bug 1082486</a>
 
     <!-- The caret will not be seen when the input is focused. -->
     <input id='i' value="abcdefghd" style="text-indent: -10px">
   </body>
 </html>
--- a/layout/base/tests/bug646382-1-ref.html
+++ b/layout/base/tests/bug646382-1-ref.html
@@ -2,16 +2,18 @@
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   </head>
   <body onload="start()">
     <textarea onfocus="done()" style="-moz-appearance: none">س</textarea>
     <script>
       var textarea = document.querySelector("textarea");
       function start() {
+        textarea.selectionStart = 0;
+        textarea.selectionEnd = 0;
         textarea.focus();
       }
       function done() {
         document.documentElement.removeAttribute("class");
       }
     </script>
   </body>
 </html>
--- a/layout/base/tests/bug646382-2-ref.html
+++ b/layout/base/tests/bug646382-2-ref.html
@@ -1,14 +1,16 @@
 <html class="reftest-wait">
   <body onload="start()">
     <textarea dir="rtl" onfocus="done()" style="-moz-appearance: none">s</textarea>
     <script>
       var textarea = document.querySelector("textarea");
       function start() {
+        textarea.selectionStart = 0;
+        textarea.selectionEnd = 0;
         textarea.focus();
       }
       function done() {
         document.documentElement.removeAttribute("class");
       }
     </script>
   </body>
 </html>
--- a/layout/base/tests/bug664087-1-ref.html
+++ b/layout/base/tests/bug664087-1-ref.html
@@ -4,16 +4,18 @@
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   </head>
   <body onload="start()">
     <textarea rows="3" onfocus="done()" spellcheck="false" style="-moz-appearance: none">אב
 ג</textarea>
     <script>
       var textarea = document.querySelector("textarea");
       function start() {
+        textarea.selectionStart = 0;
+        textarea.selectionEnd = 0;
         textarea.focus();
       }
       function done() {
         synthesizeKey("VK_LEFT", {});
         synthesizeKey("VK_LEFT", {});
         document.documentElement.removeAttribute("class");
       }
     </script>
--- a/layout/base/tests/bug664087-2-ref.html
+++ b/layout/base/tests/bug664087-2-ref.html
@@ -4,16 +4,18 @@
     <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   </head>
   <body onload="start()">
     <textarea dir="rtl" onfocus="done()" spellcheck="false" style="-moz-appearance: none">ab
 c</textarea>
     <script>
       var textarea = document.querySelector("textarea");
       function start() {
+        textarea.selectionStart = 0;
+        textarea.selectionEnd = 0;
         textarea.focus();
       }
       function done() {
         synthesizeKey("VK_RIGHT", {});
         synthesizeKey("VK_RIGHT", {});
         document.documentElement.removeAttribute("class");
       }
     </script>
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -298,19 +298,23 @@ nsTextControlFrame::EnsureEditorInitiali
     nsresult rv = txtCtrl->CreateEditor();
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_STATE(weakFrame.IsAlive());
 
     // Set mEditorHasBeenInitialized so that subsequent calls will use the
     // editor.
     mEditorHasBeenInitialized = true;
 
-    // Set the selection to the beginning of the text field.
+    nsAutoString val;
+    txtCtrl->GetTextEditorValue(val, true);
+    int32_t length = val.Length();
+
+    // Set the selection to the end of the text field. (bug 1287655)
     if (weakFrame.IsAlive()) {
-      SetSelectionEndPoints(0, 0);
+      SetSelectionEndPoints(length, length);
     }
   }
   NS_ENSURE_STATE(weakFrame.IsAlive());
   return NS_OK;
 }
 
 nsresult
 nsTextControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
@@ -421,17 +425,17 @@ nsTextControlFrame::AppendAnonymousConte
   nsIContent* root = txtCtrl->GetRootEditorNode();
   if (root) {
     aElements.AppendElement(root);
   }
 
   nsIContent* placeholder = txtCtrl->GetPlaceholderNode();
   if (placeholder && !(aFilter & nsIContent::eSkipPlaceholderContent))
     aElements.AppendElement(placeholder);
-  
+
 }
 
 nscoord
 nsTextControlFrame::GetPrefISize(nsRenderingContext* aRenderingContext)
 {
     DebugOnly<nscoord> result = 0;
     DISPLAY_PREF_WIDTH(this, result);
 
@@ -922,49 +926,49 @@ nsTextControlFrame::SetSelectionRange(in
 
 
 NS_IMETHODIMP
 nsTextControlFrame::SetSelectionStart(int32_t aSelectionStart)
 {
   nsresult rv = EnsureEditorInitialized();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  int32_t selStart = 0, selEnd = 0; 
+  int32_t selStart = 0, selEnd = 0;
 
   rv = GetSelectionRange(&selStart, &selEnd);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aSelectionStart > selEnd) {
     // Collapse to the new start point.
-    selEnd = aSelectionStart; 
+    selEnd = aSelectionStart;
   }
 
   selStart = aSelectionStart;
-  
+
   return SetSelectionEndPoints(selStart, selEnd);
 }
 
 NS_IMETHODIMP
 nsTextControlFrame::SetSelectionEnd(int32_t aSelectionEnd)
 {
   nsresult rv = EnsureEditorInitialized();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  int32_t selStart = 0, selEnd = 0; 
+  int32_t selStart = 0, selEnd = 0;
 
   rv = GetSelectionRange(&selStart, &selEnd);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aSelectionEnd < selStart) {
     // Collapse to the new end point.
-    selStart = aSelectionEnd; 
+    selStart = aSelectionEnd;
   }
 
   selEnd = aSelectionEnd;
-  
+
   return SetSelectionEndPoints(selStart, selEnd);
 }
 
 nsresult
 nsTextControlFrame::OffsetToDOMPoint(int32_t aOffset,
                                      nsIDOMNode** aResult,
                                      int32_t* aPosition)
 {
@@ -1041,17 +1045,17 @@ nsTextControlFrame::GetSelectionRange(in
     *aDirection = eNone;
   }
 
   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
   NS_ASSERTION(txtCtrl, "Content not a text control element");
   nsISelectionController* selCon = txtCtrl->GetSelectionController();
   NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
   nsCOMPtr<nsISelection> selection;
-  rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));  
+  rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
 
   dom::Selection* sel = selection->AsSelection();
   if (aDirection) {
     nsDirection direction = sel->GetSelectionDirection();
     if (direction == eDirNext) {
       *aDirection = eForward;
@@ -1180,17 +1184,17 @@ nsTextControlFrame::GetText(nsString& aT
   }
   return rv;
 }
 
 
 nsresult
 nsTextControlFrame::GetPhonetic(nsAString& aPhonetic)
 {
-  aPhonetic.Truncate(0); 
+  aPhonetic.Truncate(0);
 
   nsCOMPtr<nsIEditor> editor;
   nsresult rv = GetEditor(getter_AddRefs(editor));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIEditorIMESupport> imeSupport = do_QueryInterface(editor);
   if (imeSupport) {
     nsCOMPtr<nsIPhonetic> phonetic = do_QueryInterface(imeSupport);
--- a/layout/forms/test/bug287446_subframe.html
+++ b/layout/forms/test/bug287446_subframe.html
@@ -13,23 +13,23 @@
 
       window.addEventListener("message",
         function(evt) {
           var t = $("target");
           if (evt.data == "start") {
             doIs(t.value, "Test", "Shouldn't have lost our initial value");
             t.focus();
             sendString("Foo");
-            doIs(t.value, "FooTest", "Typing should work");
+            doIs(t.value, "TestFoo", "Typing should work");
             window.parent.postMessage("c", "*");
           } else {
             doIs(evt.data, "continue", "Unexpected message");
-            doIs(t.value, "FooTest", "Shouldn't have lost our typed value");
+            doIs(t.value, "TestFoo", "Shouldn't have lost our typed value");
             sendString("Bar");
-            doIs(t.value, "BarFooTest", "Typing should still work");
+            doIs(t.value, "TestFooBar", "Typing should still work");
             window.parent.postMessage("f", "*");
           }
         },
         "false");
       
     </script>
   </head>
   <body>
--- a/layout/forms/test/test_bug353539.html
+++ b/layout/forms/test/test_bug353539.html
@@ -33,16 +33,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="application/javascript">
 
 /** Test for Bug 353539 **/
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   var area = document.getElementById("area");
 
   is(area.scrollTop, 0, "The textarea should not be scrolled initially");
+  area.selectionStart = 0;
+  area.selectionEnd = 0;
   area.focus();
   setTimeout(function() {
     is(area.scrollTop, 0, "The textarea's insertion point should not be scrolled into view");
 
     SimpleTest.finish();
   }, 0);
 });
 
--- a/layout/forms/test/test_bug534785.html
+++ b/layout/forms/test/test_bug534785.html
@@ -28,27 +28,27 @@ SimpleTest.waitForExplicitFinish();
 
 SimpleTest.waitForFocus(function() {
   var i = document.querySelector("input");
   i.addEventListener("focus", function() {
     is(i.value, "test", "Sanity check");
 
     is(document.activeElement, i, "Should be focused before frame reconstruction");
     synthesizeKey("1", {});
-    is(i.value, "1test", "Can accept keyboard events before frame reconstruction");
+    is(i.value, "test1", "Can accept keyboard events before frame reconstruction");
 
     // force frame reconstruction
     i.style.display = "none";
     document.offsetHeight;
     i.style.display = "";
     document.offsetHeight;
 
     is(document.activeElement, i, "Should be focused after frame reconstruction");
     synthesizeKey("2", {});
-    is(i.value, "12test", "Can accept keyboard events after frame reconstruction");
+    is(i.value, "test12", "Can accept keyboard events after frame reconstruction");
 
     // Make sure reframing happens gracefully
     var reframeDiv = document.getElementById("reframe");
     var textAreaWithoutValue = reframeDiv.querySelectorAll("textarea")[0];
     var textAreaWithValue = reframeDiv.querySelectorAll("textarea")[1];
     var inputWithoutValue = reframeDiv.querySelectorAll("input")[0];
     var inputWithValue = reframeDiv.querySelectorAll("input")[1];
     reframeDiv.style.display = "none";
--- a/layout/forms/test/test_bug542914.html
+++ b/layout/forms/test/test_bug542914.html
@@ -75,19 +75,19 @@ function runTests(callback, type) {
   document.body.offsetHeight;
 
   // Make sure dynamically injected inputs work as expected
   is(d.value, "", "Dynamic control's initial value should be empty");
   d.value = "new";
   d.focus();
   is(d.value, "new", "Dynamic control's value can be set before initialization");
   sendChar("x");
-  is(d.value, "xnew", "Dynamic control accepts keyboard input without explicit initialization");
+  is(d.value, "newx", "Dynamic control accepts keyboard input without explicit initialization");
   $("display").removeChild(d);
-  is(d.value, "xnew", "Dynamic control retains value after being removed from the document");
+  is(d.value, "newx", "Dynamic control retains value after being removed from the document");
 
   callback();
 }
 
 var gPreviousType = "text";
 function setTypes(aType) {
   var content = document.getElementById("display");
   content.innerHTML = content.innerHTML.replace(gPreviousType, aType);
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -385,18 +385,18 @@ nsHTMLScrollFrame::TryLayout(ScrollReflo
     compositionSize.width /= resolution;
     compositionSize.height /= resolution;
     visualScrollPortSize = nsSize(std::max(0, compositionSize.width - vScrollbarDesiredWidth),
                                   std::max(0, compositionSize.height - hScrollbarDesiredHeight));
   }
 
   if (!aForce) {
     nsRect scrolledRect =
-      mHelper.GetScrolledRectInternal(aState->mContentsOverflowAreas.ScrollableOverflow(),
-                                     scrollPortSize);
+      mHelper.GetUnsnappedScrolledRectInternal(aState->mContentsOverflowAreas.ScrollableOverflow(),
+                                               scrollPortSize);
     nscoord oneDevPixel = aState->mBoxState.PresContext()->DevPixelsToAppUnits(1);
 
     // If the style is HIDDEN then we already know that aAssumeHScroll is false
     if (aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) {
       bool wantHScrollbar =
         aState->mStyles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL ||
         scrolledRect.XMost() >= visualScrollPortSize.width + oneDevPixel ||
         scrolledRect.x <= -oneDevPixel;
@@ -681,18 +681,18 @@ nsHTMLScrollFrame::ReflowContents(Scroll
   // where the ideal case doesn't have a scrollbar?
   if ((aState->mReflowedContentsWithHScrollbar || aState->mReflowedContentsWithVScrollbar) &&
       aState->mStyles.mVertical != NS_STYLE_OVERFLOW_SCROLL &&
       aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_SCROLL) {
     nsSize insideBorderSize =
       ComputeInsideBorderSize(aState,
                               nsSize(kidDesiredSize.Width(), kidDesiredSize.Height()));
     nsRect scrolledRect =
-      mHelper.GetScrolledRectInternal(kidDesiredSize.ScrollableOverflow(),
-                                     insideBorderSize);
+      mHelper.GetUnsnappedScrolledRectInternal(kidDesiredSize.ScrollableOverflow(),
+                                               insideBorderSize);
     if (nsRect(nsPoint(0, 0), insideBorderSize).Contains(scrolledRect)) {
       // Let's pretend we had no scrollbars coming in here
       ReflowScrolledFrame(aState, false, false, &kidDesiredSize, false);
     }
   }
 
   // Try vertical scrollbar settings that leave the vertical scrollbar unchanged.
   // Do this first because changing the vertical scrollbar setting is expensive,
@@ -733,18 +733,18 @@ nsHTMLScrollFrame::PlaceScrollArea(const
   nsIFrame *scrolledFrame = mHelper.mScrolledFrame;
   // Set the x,y of the scrolled frame to the correct value
   scrolledFrame->SetPosition(mHelper.mScrollPort.TopLeft() - aScrollPosition);
 
   nsRect scrolledArea;
   // Preserve the width or height of empty rects
   nsSize portSize = mHelper.mScrollPort.Size();
   nsRect scrolledRect =
-    mHelper.GetScrolledRectInternal(aState.mContentsOverflowAreas.ScrollableOverflow(),
-                                   portSize);
+    mHelper.GetUnsnappedScrolledRectInternal(aState.mContentsOverflowAreas.ScrollableOverflow(),
+                                             portSize);
   scrolledArea.UnionRectEdges(scrolledRect,
                               nsRect(nsPoint(0,0), portSize));
 
   // Store the new overflow area. Note that this changes where an outline
   // of the scrolled frame would be painted, but scrolled frames can't have
   // outlines (the outline would go on this scrollframe instead).
   // Using FinishAndStoreOverflow is needed so the overflow rect
   // gets set correctly.  It also messes with the overflow rect in the
@@ -3301,17 +3301,23 @@ ScrollFrameHelper::BuildDisplayList(nsDi
         if (mClipAllDescendants) {
           inactiveScrollClip = clipStateForScrollClip.InsertInactiveScrollClipForContentDescendants(aBuilder, sf);
         } else {
           inactiveScrollClip = clipStateForScrollClip.InsertInactiveScrollClipForContainingBlockDescendants(aBuilder, sf);
         }
         MOZ_ASSERT(!inactiveScrollClip->mIsAsyncScrollable);
       }
 
-      DisplayListClipState::AutoSaveRestore displayPortClipState(aBuilder);
+      // Clip our contents to the unsnapped scrolled rect. This makes sure that
+      // we don't have display items over the subpixel seam at the edge of the
+      // scrolled area.
+      DisplayListClipState::AutoSaveRestore scrolledRectClipState(aBuilder);
+      nsRect scrolledRectClip =
+        GetUnsnappedScrolledRectInternal(mScrolledFrame->GetScrollableOverflowRect(),
+                                         mScrollPort.Size()) + mScrolledFrame->GetPosition();
       if (usingDisplayPort) {
         // Clip the contents to the display port.
         // The dirty rect already acts kind of like a clip, in that
         // FrameLayerBuilder intersects item bounds and opaque regions with
         // it, but it doesn't have the consistent snapping behavior of a
         // true clip.
         // For a case where this makes a difference, imagine the following
         // scenario: The display port has an edge that falls on a fractional
@@ -3319,18 +3325,20 @@ ScrollFrameHelper::BuildDisplayList(nsDi
         // whole display port up until that fractional edge, and there is a
         // transparent display item that overlaps the edge. We want to prevent
         // this transparent item from enlarging the scrolled layer's visible
         // region beyond its opaque region. The dirty rect doesn't do that -
         // it gets rounded out, whereas a true clip gets rounded to nearest
         // pixels.
         // If there is no display port, we don't need this because the clip
         // from the scroll port is still applied.
-        displayPortClipState.ClipContainingBlockDescendants(dirtyRect + aBuilder->ToReferenceFrame(mOuter));
+        scrolledRectClip = scrolledRectClip.Intersect(dirtyRect);
       }
+      scrolledRectClipState.ClipContainingBlockDescendants(
+        scrolledRectClip + aBuilder->ToReferenceFrame(mOuter));
 
       mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, scrolledContent);
     }
 
     if (contentBoxClipForNonCaretContent) {
       DisplayListClipState::AutoSaveRestore contentBoxClipState(aBuilder);
       if (mClipAllDescendants) {
         contentBoxClipState.ClipContentDescendants(*contentBoxClipForNonCaretContent);
@@ -5561,53 +5569,112 @@ ScrollFrameHelper::GetBorderRadii(const 
     ReduceRadii(border.left, border.bottom,
                 aRadii[NS_CORNER_BOTTOM_LEFT_X],
                 aRadii[NS_CORNER_BOTTOM_LEFT_Y]);
   }
 
   return true;
 }
 
+static nscoord
+SnapCoord(nscoord aCoord, double aRes, nscoord aAppUnitsPerPixel)
+{
+  double snappedToLayerPixels = NS_round((aRes*aCoord)/aAppUnitsPerPixel);
+  return NSToCoordRoundWithClamp(snappedToLayerPixels*aAppUnitsPerPixel/aRes);
+}
+
 nsRect
 ScrollFrameHelper::GetScrolledRect() const
 {
   nsRect result =
-    GetScrolledRectInternal(mScrolledFrame->GetScrollableOverflowRect(),
-                            mScrollPort.Size());
+    GetUnsnappedScrolledRectInternal(mScrolledFrame->GetScrollableOverflowRect(),
+                                     mScrollPort.Size());
 
   if (result.width < mScrollPort.width) {
     NS_WARNING("Scrolled rect smaller than scrollport?");
   }
   if (result.height < mScrollPort.height) {
     NS_WARNING("Scrolled rect smaller than scrollport?");
   }
+
+  // Expand / contract the result by up to half a layer pixel so that scrolling
+  // to the right / bottom edge does not change the layer pixel alignment of
+  // the scrolled contents.
+  // For that, we first convert the scroll port and the scrolled rect to rects
+  // relative to the reference frame, since that's the space where painting does
+  // snapping.
+  nsSize scrollPortSize = GetScrollPositionClampingScrollPortSize();
+  nsIFrame* referenceFrame = nsLayoutUtils::GetReferenceFrame(mOuter);
+  nsPoint toReferenceFrame = mOuter->GetOffsetToCrossDoc(referenceFrame);
+  nsRect scrollPort(mScrollPort.TopLeft() + toReferenceFrame, scrollPortSize);
+  nsRect scrolledRect = result + scrollPort.TopLeft();
+
+  if (scrollPort.Overflows() || scrolledRect.Overflows()) {
+    return result;
+  }
+
+  // Now, snap the bottom right corner of both of these rects.
+  // We snap to layer pixels, so we need to respect the layer's scale.
+  nscoord appUnitsPerDevPixel = mScrolledFrame->PresContext()->AppUnitsPerDevPixel();
+  gfxSize scale = FrameLayerBuilder::GetPaintedLayerScaleForFrame(mScrolledFrame);
+  if (scale.IsEmpty()) {
+    scale = gfxSize(1.0f, 1.0f);
+  }
+
+  // Compute bounds for the scroll position, and computed the snapped scrolled
+  // rect from the scroll position bounds.
+  nscoord snappedScrolledAreaBottom = SnapCoord(scrolledRect.YMost(), scale.height, appUnitsPerDevPixel);
+  nscoord snappedScrollPortBottom = SnapCoord(scrollPort.YMost(), scale.height, appUnitsPerDevPixel);
+  nscoord maximumScrollOffsetY = snappedScrolledAreaBottom - snappedScrollPortBottom;
+  result.SetBottomEdge(scrollPort.height + maximumScrollOffsetY);
+
+  if (GetScrolledFrameDir() == NS_STYLE_DIRECTION_LTR) {
+    nscoord snappedScrolledAreaRight = SnapCoord(scrolledRect.XMost(), scale.width, appUnitsPerDevPixel);
+    nscoord snappedScrollPortRight = SnapCoord(scrollPort.XMost(), scale.width, appUnitsPerDevPixel);
+    nscoord maximumScrollOffsetX = snappedScrolledAreaRight - snappedScrollPortRight;
+    result.SetRightEdge(scrollPort.width + maximumScrollOffsetX);
+  } else {
+    // In RTL, the scrolled area's right edge is at scrollPort.XMost(),
+    // and the scrolled area's x position is zero or negative. We want
+    // the right edge to stay flush with the scroll port, so we snap the
+    // left edge.
+    nscoord snappedScrolledAreaLeft = SnapCoord(scrolledRect.x, scale.width, appUnitsPerDevPixel);
+    nscoord snappedScrollPortLeft = SnapCoord(scrollPort.x, scale.width, appUnitsPerDevPixel);
+    nscoord minimumScrollOffsetX = snappedScrolledAreaLeft - snappedScrollPortLeft;
+    result.SetLeftEdge(minimumScrollOffsetX);
+  }
+
   return result;
 }
 
-nsRect
-ScrollFrameHelper::GetScrolledRectInternal(const nsRect& aScrolledFrameOverflowArea,
-                                               const nsSize& aScrollPortSize) const
-{
-  uint8_t frameDir = IsLTR() ? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
-
+
+uint8_t
+ScrollFrameHelper::GetScrolledFrameDir() const
+{
   // If the scrolled frame has unicode-bidi: plaintext, the paragraph
   // direction set by the text content overrides the direction of the frame
   if (mScrolledFrame->StyleTextReset()->mUnicodeBidi &
       NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
     nsIFrame* childFrame = mScrolledFrame->PrincipalChildList().FirstChild();
     if (childFrame) {
-      frameDir =
-        (nsBidiPresUtils::ParagraphDirection(childFrame) == NSBIDI_LTR)
+      return (nsBidiPresUtils::ParagraphDirection(childFrame) == NSBIDI_LTR)
           ? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
     }
   }
 
+  return IsLTR() ? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
+}
+
+nsRect
+ScrollFrameHelper::GetUnsnappedScrolledRectInternal(const nsRect& aScrolledFrameOverflowArea,
+                                                    const nsSize& aScrollPortSize) const
+{
   return nsLayoutUtils::GetScrolledRect(mScrolledFrame,
                                         aScrolledFrameOverflowArea,
-                                        aScrollPortSize, frameDir);
+                                        aScrollPortSize, GetScrolledFrameDir());
 }
 
 nsMargin
 ScrollFrameHelper::GetActualScrollbarSizes() const
 {
   nsRect r = mOuter->GetPaddingRect() - mOuter->GetPosition();
 
   return nsMargin(mScrollPort.y - r.y,
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -303,28 +303,28 @@ public:
    * Currently it allows scrolling down and to the right for
    * nsHTMLScrollFrames with LTR directionality and for all
    * nsXULScrollFrames, and allows scrolling down and to the left for
    * nsHTMLScrollFrames with RTL directionality.
    */
   nsRect GetScrolledRect() const;
 
   /**
-   * GetScrolledRectInternal is designed to encapsulate deciding which
+   * GetUnsnappedScrolledRectInternal is designed to encapsulate deciding which
    * directions of overflow should be reachable by scrolling and which
    * should not.  Callers should NOT depend on it having any particular
    * behavior (although nsXULScrollFrame currently does).
    * 
    * Currently it allows scrolling down and to the right for
    * nsHTMLScrollFrames with LTR directionality and for all
    * nsXULScrollFrames, and allows scrolling down and to the left for
    * nsHTMLScrollFrames with RTL directionality.
    */
-  nsRect GetScrolledRectInternal(const nsRect& aScrolledOverflowArea,
-                                 const nsSize& aScrollPortSize) const;
+  nsRect GetUnsnappedScrolledRectInternal(const nsRect& aScrolledOverflowArea,
+                                          const nsSize& aScrollPortSize) const;
 
   uint32_t GetScrollbarVisibility() const {
     return (mHasVerticalScrollbar ? nsIScrollableFrame::VERTICAL : 0) |
            (mHasHorizontalScrollbar ? nsIScrollableFrame::HORIZONTAL : 0);
   }
   nsMargin GetActualScrollbarSizes() const;
   nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState);
   nscoord GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState,
@@ -617,16 +617,17 @@ protected:
                           nsIScrollbarMediator::ScrollSnapMode aSnap
                             = nsIScrollbarMediator::DISABLE_SNAP);
 
   void CompleteAsyncScroll(const nsRect &aRange, nsIAtom* aOrigin = nullptr);
 
   bool HasPluginFrames();
   bool HasPerspective() const;
   bool HasBgAttachmentLocal() const;
+  uint8_t GetScrolledFrameDir() const;
 
   static void EnsureFrameVisPrefsCached();
   static bool sFrameVisPrefsCached;
   // The number of scrollports wide/high to expand when tracking frame visibility.
   static uint32_t sHorzExpandScrollPort;
   static uint32_t sVertExpandScrollPort;
   // The fraction of the scrollport we allow to scroll by before we schedule
   // an update of frame visibility.
--- a/layout/generic/test/test_bug784410.html
+++ b/layout/generic/test/test_bug784410.html
@@ -4,17 +4,17 @@
   <title>Test bug 784410</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script src="/tests/SimpleTest/paint_listener.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
-<div id="outer" style="overflow:auto; height:200px; border:2px dotted black;" onscroll="doneScroll()">
+<div id="outer" style="overflow:auto; height:200px; border:2px dotted black; transform: translateY(1px)" onscroll="doneScroll()">
   <div id="d" style="overflow:auto; height:102px;" onscroll="doneScroll()">
     <div id="inner" style="height:100.1px; border:1px solid black; background:yellow;">Hello</div>
   </div>
   <div style="height:500px;"></div>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript;version=1.7">
 var sel = window.getSelection();
--- a/layout/generic/test/test_bug791616.html
+++ b/layout/generic/test/test_bug791616.html
@@ -6,17 +6,17 @@
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <style>
 #t {
     overflow: auto;
     position: absolute;
     left: 200px;
     top: 100px;
-    font: 14px/1.1em "Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace;
+    font: 14px/1.3em "Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace;
 }
   </style>
 </head>
 <body>
 <p id="display"></p>
 <div id="t" contenteditable>
   <div>66666666666666</div>
   <div id="target">777777777777777777777777777777777777777</div>
--- a/layout/reftests/bugs/240933-1.html
+++ b/layout/reftests/bugs/240933-1.html
@@ -7,13 +7,13 @@
 
 </textarea>
 <textarea id="tb">
 
 abc
 
 </textarea>
 
-<div id="coords1">0</div>
-<div id="coords2">0</div>
+<div id="coords1">6</div>
+<div id="coords2">6</div>
 
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/scrolling/fractional-scroll-area-invalidation.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html lang="en" reftest-async-scroll>
+<meta charset="utf-8">
+<title>Make sure the scrolled layer is not invalidated when you scroll all the way to the bottom</title>
+
+<style>
+
+body {
+  margin: 0;
+}
+
+.scrollbox {
+  margin: 50px;
+  width: 200px;
+  height: 200px;
+  overflow: auto;
+}
+
+.scrolled-contents {
+  height: 150.2px;
+  padding-top: 150px;
+}
+
+.reftest-no-paint {
+  margin: 0 20px;
+  border: 1px solid blue;
+  height: 25px;
+}
+
+</style>
+
+<body>
+
+<div class="scrollbox"
+     reftest-displayport-x="0" reftest-displayport-y="0"
+     reftest-displayport-w="200" reftest-displayport-h="200"
+     reftest-async-scroll-x="0" reftest-async-scroll-y="0">
+  <div class="scrolled-contents">
+    <div class="reftest-no-paint">
+      <!-- This element has the magic "reftest-no-paint" class which
+           constitutes the actual test here. -->
+    </div>
+  </div>
+</div>
+
+<script>
+
+var scrollbox = document.querySelector(".scrollbox");
+scrollbox.scrollTop = 2;
+scrollbox.scrollTop = 1;
+scrollbox.scrollTop = 0;
+
+function doTest() {
+  scrollbox.scrollTop = 999;
+  document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/scrolling/fractional-scroll-area.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Fractional scroll area position / size</title>
+
+<style>
+
+body {
+  margin: 0;
+}
+
+#scrollbox {
+  width: 200px;
+  overflow: hidden;
+  background: red;
+}
+
+#scrolled-content {
+  background: lime;
+  box-sizing: border-box;
+  border: solid black;
+  border-width: 1px 0;
+}
+
+</style>
+
+<div id="scrollbox">
+  <div id="scrolled-content"></div>
+</div>
+
+<script>
+
+function getFloatQueryParams(defaultValues) {
+  let result = Object.assign({}, defaultValues);
+  for (let chunk of location.search.substr(1).split("&")) {
+    let parts = chunk.split("=");
+    result[parts[0]] = parseFloat(parts[1]);
+  }
+  return result;
+}
+
+let params = getFloatQueryParams({
+  top: 0,
+  outerBottom: 100,
+  innerBottom: 100,
+  borderTop: 0,
+  borderBottom: 0,
+  scrollBefore: 0,
+  scrollAfter: undefined,
+  offsetAfter: undefined,
+});
+
+let scrollArea = document.getElementById("scrollbox");
+let scrolledContent = document.getElementById("scrolled-content");
+
+scrollArea.style.marginTop = params.top + "px";
+scrollArea.style.height = (params.outerBottom - params.top) + "px";
+scrolledContent.style.height =  (params.innerBottom - params.top) + "px";
+
+scrollArea.scrollTop = 1;
+scrollArea.scrollTop = 2;
+scrollArea.scrollTop = params.scrollBefore;
+
+window.addEventListener("MozReftestInvalidate", function () {
+  if (params.scrollAfter !== undefined) {
+    scrollArea.scrollTop = params.scrollAfter;
+  }
+  if (params.offsetAfter !== undefined) {
+    document.body.style.marginTop = params.offsetAfter + "px";
+  }
+  document.documentElement.className = "";
+});
+
+</script>
--- a/layout/reftests/scrolling/reftest.list
+++ b/layout/reftests/scrolling/reftest.list
@@ -31,8 +31,57 @@ fuzzy-if(Android,5,20000) == uncovering-
 skip-if(B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,121,3721) == less-than-scrollbar-height.html less-than-scrollbar-height-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) == huge-horizontal-overflow.html huge-horizontal-overflow-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) == huge-vertical-overflow.html huge-vertical-overflow-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 fuzzy-if(asyncPan&&!layersGPUAccelerated,102,6818) == iframe-scrolling-attr-1.html iframe-scrolling-attr-ref.html
 skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,6818) == iframe-scrolling-attr-2.html iframe-scrolling-attr-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 == frame-scrolling-attr-1.html frame-scrolling-attr-ref.html
 fuzzy-if(asyncPan&&!layersGPUAccelerated,102,2420) == frame-scrolling-attr-2.html frame-scrolling-attr-ref.html
 == move-item.html move-item-ref.html # bug 1125750
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+!= fractional-scroll-area-invalidation.html about:blank
--- a/layout/reftests/text-overflow/reftest.list
+++ b/layout/reftests/text-overflow/reftest.list
@@ -17,17 +17,17 @@ skip-if(B2G||Mulet) random-if(/^Windows\
 HTTP(..) == marker-shadow.html marker-shadow-ref.html
 == aligned-baseline.html aligned-baseline-ref.html
 skip-if(Android||B2G) fuzzy-if(skiaContent,1,5) == clipped-elements.html clipped-elements-ref.html
 HTTP(..) == theme-overflow.html theme-overflow-ref.html
 skip-if(B2G||Mulet) HTTP(..) == table-cell.html table-cell-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(Mulet) fuzzy-if(gtkWidget,10,32) HTTP(..) == two-value-syntax.html two-value-syntax-ref.html # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables
 skip-if(B2G||Mulet) HTTP(..) == single-value.html single-value-ref.html  # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) fuzzy-if(gtkWidget,10,2) HTTP(..) == atomic-under-marker.html atomic-under-marker-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
-fuzzy(1,702) skip-if(Android||B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,12352) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
+fuzzy(1,2616) skip-if(Android||B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,12352) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 HTTP(..) == combobox-zoom.html combobox-zoom-ref.html
 
 # The vertical-text pref setting can be removed after bug 1138384 lands
 pref(layout.css.vertical-text.enabled,true) == vertical-decorations-1.html vertical-decorations-1-ref.html
 pref(layout.css.vertical-text.enabled,true) == vertical-decorations-2.html vertical-decorations-2-ref.html
 pref(layout.css.vertical-text.enabled,true) != vertical-decorations-1.html vertical-decorations-1-2-notref.html
 pref(layout.css.vertical-text.enabled,true) != vertical-decorations-2.html vertical-decorations-1-2-notref.html
 pref(layout.css.vertical-text.enabled,true) == vertical-decorations-3.html vertical-decorations-3-ref.html
--- a/layout/style/nsCSSDataBlock.cpp
+++ b/layout/style/nsCSSDataBlock.cpp
@@ -64,19 +64,34 @@ TryToStartImageLoadOnValue(const nsCSSVa
 #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
     // The 'mask-image' property accepts local reference URIs.
     // For example,
     //   mask-image: url(#mask_id); // refer to a SVG mask element, whose id is
     //                              // "mask_id", in the current document.
     // For such 'mask-image' values (pointing to an in-document element),
     // there is no need to trigger image download.
     if (aProperty == eCSSProperty_mask_image) {
-      nsIURI* docURI = aDocument->GetDocumentURI();
+      // Filter out all fragment URLs.
+      // Since nsCSSValue::GetURLStructValue runs much faster than
+      // nsIURI::EqualsExceptRef bellow, we get performance gain by this
+      // early return.
+      URLValue* urlValue = aValue.GetURLStructValue();
+      if (urlValue->GetLocalURLFlag()) {
+        return;
+      }
+
+      // Even though urlValue is not a fragment URL, it might still refer to
+      // an internal resource.
+      // For example, aDocument base URL is "http://foo/index.html" and
+      // intentionally references a mask-image at
+      // url(http://foo/index.html#mask) which still refers to a resource in
+      // aDocument.
       nsIURI* imageURI = aValue.GetURLValue();
       if (imageURI) {
+        nsIURI* docURI = aDocument->GetDocumentURI();
         bool isEqualExceptRef = false;
         nsresult  rv = imageURI->EqualsExceptRef(docURI, &isEqualExceptRef);
         if (NS_SUCCEEDED(rv) && isEqualExceptRef) {
           return;
         }
       }
     }
 #endif
--- a/media/ffvpx/changes.patch
+++ b/media/ffvpx/changes.patch
@@ -45,8 +45,21 @@ index 9fb8d0a..97ad3b9 100644
      rgba_color[3] = 255;
  
      if (!av_strcasecmp(color_string2, "random") || !av_strcasecmp(color_string2, "bikeshed")) {
 -        int rgba = av_get_random_seed();
 +        int rgba = 0xffffffff; /* av_get_random_seed(); */
          rgba_color[0] = rgba >> 24;
          rgba_color[1] = rgba >> 16;
          rgba_color[2] = rgba >> 8;
+diff --git a/media/ffvpx/libavcodec/options.c b/media/ffvpx/libavcodec/options.c
+index d8e3dbf..f25df2a 100644
+--- a/media/ffvpx/libavcodec/options.c
++++ b/media/ffvpx/libavcodec/options.c
+@@ -34,7 +34,7 @@
+ #include <string.h>
+ 
+ FF_DISABLE_DEPRECATION_WARNINGS
+-#include "options_table.h"
++#include "ff_options_table.h"
+ FF_ENABLE_DEPRECATION_WARNINGS
+ 
+ static const char* context_to_name(void* ptr) {
--- a/media/ffvpx/libavcodec/avcodec.symbols
+++ b/media/ffvpx/libavcodec/avcodec.symbols
@@ -77,19 +77,16 @@ av_vorbis_parse_reset
 av_xiphlacing
 avcodec_align_dimensions
 avcodec_align_dimensions2
 avcodec_alloc_context3
 avcodec_chroma_pos_to_enum
 avcodec_close
 avcodec_configuration
 avcodec_copy_context
-avcodec_dct_alloc
-avcodec_dct_get_class
-avcodec_dct_init
 avcodec_decode_audio4
 avcodec_decode_subtitle2
 avcodec_decode_video2
 avcodec_default_execute
 avcodec_default_execute2
 avcodec_default_get_buffer2
 avcodec_default_get_format
 avcodec_descriptor_get
deleted file mode 100644
--- a/media/ffvpx/libavcodec/avdct.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2014 Michael Niedermayer <michaelni@gmx.at>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "avcodec.h"
-#include "idctdsp.h"
-#include "fdctdsp.h"
-#include "pixblockdsp.h"
-#include "avdct.h"
-
-#define OFFSET(x) offsetof(AVDCT,x)
-#define DEFAULT 0 //should be NAN but it does not work as it is not a constant in glibc as required by ANSI/ISO C
-//these names are too long to be readable
-#define V AV_OPT_FLAG_VIDEO_PARAM
-#define A AV_OPT_FLAG_AUDIO_PARAM
-#define E AV_OPT_FLAG_ENCODING_PARAM
-#define D AV_OPT_FLAG_DECODING_PARAM
-
-static const AVOption avdct_options[] = {
-{"dct", "DCT algorithm", OFFSET(dct_algo), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|E, "dct"},
-{"auto", "autoselect a good one", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_AUTO }, INT_MIN, INT_MAX, V|E, "dct"},
-{"fastint", "fast integer (experimental / for debugging)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FASTINT }, INT_MIN, INT_MAX, V|E, "dct"},
-{"int", "accurate integer", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_INT }, INT_MIN, INT_MAX, V|E, "dct"},
-{"mmx", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_MMX }, INT_MIN, INT_MAX, V|E, "dct"},
-{"altivec", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_ALTIVEC }, INT_MIN, INT_MAX, V|E, "dct"},
-{"faan", "floating point AAN DCT (experimental / for debugging)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FAAN }, INT_MIN, INT_MAX, V|E, "dct"},
-
-{"idct", "select IDCT implementation", OFFSET(idct_algo), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|E|D, "idct"},
-{"auto", "autoselect a good one", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_AUTO }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"int", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_INT }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simple", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLE }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simplemmx", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEMMX }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"arm", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ARM }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"altivec", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ALTIVEC }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#if FF_API_ARCH_SH4
-{"sh4", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SH4 }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#endif
-{"simplearm", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARM }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simplearmv5te", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV5TE }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simplearmv6", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV6 }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simpleneon", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLENEON }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#if FF_API_ARCH_ALPHA
-{"simplealpha", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEALPHA }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#endif
-#if FF_API_UNUSED_MEMBERS
-{"ipp", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_IPP }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#endif
-{"xvid", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"xvidmmx", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"faani", "floating point AAN IDCT (experimental / for debugging)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_FAAN }, INT_MIN, INT_MAX, V|D|E, "idct"},
-{"simpleauto", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEAUTO }, INT_MIN, INT_MAX, V|E|D, "idct"},
-
-{"bits_per_sample", "", OFFSET(bits_per_sample), AV_OPT_TYPE_INT, {.i64 = 8 }, 0, 14, 0,},
-{NULL},
-};
-
-static const AVClass avdct_class = {
-    .class_name              = "AVDCT",
-    .option                  = avdct_options,
-    .version                 = LIBAVUTIL_VERSION_INT,
-};
-
-const AVClass *avcodec_dct_get_class(void)
-{
-    return &avdct_class;
-}
-
-AVDCT *avcodec_dct_alloc(void)
-{
-    AVDCT *dsp = av_mallocz(sizeof(AVDCT));
-
-    if (!dsp)
-        return NULL;
-
-    dsp->av_class = &avdct_class;
-    av_opt_set_defaults(dsp);
-
-    return dsp;
-}
-
-int avcodec_dct_init(AVDCT *dsp)
-{
-    AVCodecContext *avctx = avcodec_alloc_context3(NULL);
-
-    if (!avctx)
-        return AVERROR(ENOMEM);
-
-    avctx->idct_algo = dsp->idct_algo;
-    avctx->dct_algo  = dsp->dct_algo;
-    avctx->bits_per_raw_sample = dsp->bits_per_sample;
-
-#define COPY(src, name) memcpy(&dsp->name, &src.name, sizeof(dsp->name))
-
-#if CONFIG_IDCTDSP
-    {
-        IDCTDSPContext idsp;
-        ff_idctdsp_init(&idsp, avctx);
-        COPY(idsp, idct);
-        COPY(idsp, idct_permutation);
-    }
-#endif
-
-#if CONFIG_FDCTDSP
-    {
-        FDCTDSPContext fdsp;
-        ff_fdctdsp_init(&fdsp, avctx);
-        COPY(fdsp, fdct);
-    }
-#endif
-
-#if CONFIG_PIXBLOCKDSP
-    {
-        PixblockDSPContext pdsp;
-        ff_pixblockdsp_init(&pdsp, avctx);
-        COPY(pdsp, get_pixels);
-    }
-#endif
-
-    avcodec_close(avctx);
-    av_free(avctx);
-
-    return 0;
-}
deleted file mode 100644
--- a/media/ffvpx/libavcodec/bsf.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <string.h>
-
-#include "libavutil/log.h"
-#include "libavutil/mem.h"
-#include "libavutil/opt.h"
-
-#include "avcodec.h"
-#include "bsf.h"
-
-struct AVBSFInternal {
-    AVPacket *buffer_pkt;
-    int eof;
-};
-
-void av_bsf_free(AVBSFContext **pctx)
-{
-    AVBSFContext *ctx;
-
-    if (!pctx || !*pctx)
-        return;
-    ctx = *pctx;
-
-    if (ctx->filter->close)
-        ctx->filter->close(ctx);
-    if (ctx->filter->priv_class && ctx->priv_data)
-        av_opt_free(ctx->priv_data);
-
-    av_opt_free(ctx);
-
-    av_packet_free(&ctx->internal->buffer_pkt);
-    av_freep(&ctx->internal);
-    av_freep(&ctx->priv_data);
-
-    avcodec_parameters_free(&ctx->par_in);
-    avcodec_parameters_free(&ctx->par_out);
-
-    av_freep(pctx);
-}
-
-static void *bsf_child_next(void *obj, void *prev)
-{
-    AVBSFContext *ctx = obj;
-    if (!prev && ctx->filter->priv_class)
-        return ctx->priv_data;
-    return NULL;
-}
-
-static const AVClass bsf_class = {
-    .class_name       = "AVBSFContext",
-    .item_name        = av_default_item_name,
-    .version          = LIBAVUTIL_VERSION_INT,
-    .child_next       = bsf_child_next,
-    .child_class_next = ff_bsf_child_class_next,
-};
-
-const AVClass *av_bsf_get_class(void)
-{
-    return &bsf_class;
-}
-
-int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
-{
-    AVBSFContext *ctx;
-    int ret;
-
-    ctx = av_mallocz(sizeof(*ctx));
-    if (!ctx)
-        return AVERROR(ENOMEM);
-
-    ctx->av_class = &bsf_class;
-    ctx->filter   = filter;
-
-    ctx->par_in  = avcodec_parameters_alloc();
-    ctx->par_out = avcodec_parameters_alloc();
-    if (!ctx->par_in || !ctx->par_out) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    ctx->internal = av_mallocz(sizeof(*ctx->internal));
-    if (!ctx->internal) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    ctx->internal->buffer_pkt = av_packet_alloc();
-    if (!ctx->internal->buffer_pkt) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    av_opt_set_defaults(ctx);
-
-    /* allocate priv data and init private options */
-    if (filter->priv_data_size) {
-        ctx->priv_data = av_mallocz(filter->priv_data_size);
-        if (!ctx->priv_data) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-        if (filter->priv_class) {
-            *(const AVClass **)ctx->priv_data = filter->priv_class;
-            av_opt_set_defaults(ctx->priv_data);
-        }
-    }
-
-    *pctx = ctx;
-    return 0;
-fail:
-    av_bsf_free(&ctx);
-    return ret;
-}
-
-int av_bsf_init(AVBSFContext *ctx)
-{
-    int ret, i;
-
-    /* check that the codec is supported */
-    if (ctx->filter->codec_ids) {
-        for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++)
-            if (ctx->par_in->codec_id == ctx->filter->codec_ids[i])
-                break;
-        if (ctx->filter->codec_ids[i] == AV_CODEC_ID_NONE) {
-            const AVCodecDescriptor *desc = avcodec_descriptor_get(ctx->par_in->codec_id);
-            av_log(ctx, AV_LOG_ERROR, "Codec '%s' (%d) is not supported by the "
-                   "bitstream filter '%s'. Supported codecs are: ",
-                   desc ? desc->name : "unknown", ctx->par_in->codec_id, ctx->filter->name);
-            for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) {
-                desc = avcodec_descriptor_get(ctx->filter->codec_ids[i]);
-                av_log(ctx, AV_LOG_ERROR, "%s (%d) ",
-                       desc ? desc->name : "unknown", ctx->filter->codec_ids[i]);
-            }
-            av_log(ctx, AV_LOG_ERROR, "\n");
-            return AVERROR(EINVAL);
-        }
-    }
-
-    /* initialize output parameters to be the same as input
-     * init below might overwrite that */
-    ret = avcodec_parameters_copy(ctx->par_out, ctx->par_in);
-    if (ret < 0)
-        return ret;
-
-    ctx->time_base_out = ctx->time_base_in;
-
-    if (ctx->filter->init) {
-        ret = ctx->filter->init(ctx);
-        if (ret < 0)
-            return ret;
-    }
-
-    return 0;
-}
-
-int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
-{
-    if (!pkt || !pkt->data) {
-        ctx->internal->eof = 1;
-        return 0;
-    }
-
-    if (ctx->internal->eof) {
-        av_log(ctx, AV_LOG_ERROR, "A non-NULL packet sent after an EOF.\n");
-        return AVERROR(EINVAL);
-    }
-
-    if (ctx->internal->buffer_pkt->data ||
-        ctx->internal->buffer_pkt->side_data_elems)
-        return AVERROR(EAGAIN);
-
-    av_packet_move_ref(ctx->internal->buffer_pkt, pkt);
-
-    return 0;
-}
-
-int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
-{
-    return ctx->filter->filter(ctx, pkt);
-}
-
-int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
-{
-    AVBSFInternal *in = ctx->internal;
-    AVPacket *tmp_pkt;
-
-    if (in->eof)
-        return AVERROR_EOF;
-
-    if (!ctx->internal->buffer_pkt->data &&
-        !ctx->internal->buffer_pkt->side_data_elems)
-        return AVERROR(EAGAIN);
-
-    tmp_pkt = av_packet_alloc();
-    if (!tmp_pkt)
-        return AVERROR(ENOMEM);
-
-    *pkt = ctx->internal->buffer_pkt;
-    ctx->internal->buffer_pkt = tmp_pkt;
-
-    return 0;
-}
new file mode 100644
--- /dev/null
+++ b/media/ffvpx/libavcodec/ff_options_table.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_OPTIONS_TABLE_H
+#define AVCODEC_OPTIONS_TABLE_H
+
+#include "libavutil/opt.h"
+static const AVOption avcodec_options[] = {
+{NULL},
+};
+
+#endif /* AVCODEC_OPTIONS_TABLE_H */
--- a/media/ffvpx/libavcodec/moz.build
+++ b/media/ffvpx/libavcodec/moz.build
@@ -8,17 +8,16 @@
 # moz.build file.
 if CONFIG['FFVPX_ASFLAGS']:
     DIRS += ['x86']
 
 SharedLibrary('mozavcodec')
 SOURCES += [
     'allcodecs.c',
     'audioconvert.c',
-    'avdct.c',
     'avpacket.c',
     'avpicture.c',
     'bitstream.c',
     'codec_desc.c',
     'dummy_funcs.c',
     'h264pred.c',
     'imgconvert.c',
     'log2_tab.c',
--- a/media/ffvpx/libavcodec/options.c
+++ b/media/ffvpx/libavcodec/options.c
@@ -29,17 +29,17 @@
 #include "libavutil/avassert.h"
 #include "libavutil/internal.h"
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include <float.h>              /* FLT_MIN, FLT_MAX */
 #include <string.h>
 
 FF_DISABLE_DEPRECATION_WARNINGS
-#include "options_table.h"
+#include "ff_options_table.h"
 FF_ENABLE_DEPRECATION_WARNINGS
 
 static const char* context_to_name(void* ptr) {
     AVCodecContext *avc= ptr;
 
     if(avc && avc->codec && avc->codec->name)
         return avc->codec->name;
     else
deleted file mode 100644
--- a/media/ffvpx/libavcodec/options_table.h
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Copyright (c) 2001 Fabrice Bellard
- * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVCODEC_OPTIONS_TABLE_H
-#define AVCODEC_OPTIONS_TABLE_H
-
-#include <float.h>
-#include <limits.h>
-#include <stdint.h>
-
-#include "libavutil/opt.h"
-#include "avcodec.h"
-#include "version.h"
-
-#define OFFSET(x) offsetof(AVCodecContext,x)
-#define DEFAULT 0 //should be NAN but it does not work as it is not a constant in glibc as required by ANSI/ISO C
-//these names are too long to be readable
-#define V AV_OPT_FLAG_VIDEO_PARAM
-#define A AV_OPT_FLAG_AUDIO_PARAM
-#define S AV_OPT_FLAG_SUBTITLE_PARAM
-#define E AV_OPT_FLAG_ENCODING_PARAM
-#define D AV_OPT_FLAG_DECODING_PARAM
-
-#define AV_CODEC_DEFAULT_BITRATE 200*1000
-
-static const AVOption avcodec_options[] = {
-{"b", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT64, {.i64 = AV_CODEC_DEFAULT_BITRATE }, 0, INT64_MAX, A|V|E},
-{"ab", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT64, {.i64 = 128*1000 }, 0, INT_MAX, A|E},
-{"bt", "Set video bitrate tolerance (in bits/s). In 1-pass mode, bitrate tolerance specifies how far "
-       "ratecontrol is willing to deviate from the target average bitrate value. This is not related "
-       "to minimum/maximum bitrate. Lowering tolerance too much has an adverse effect on quality.",
-       OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E},
-{"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|S|E|D, "flags"},
-{"unaligned", "allow decoders to produce unaligned output", 0, AV_OPT_TYPE_CONST, { .i64 = AV_CODEC_FLAG_UNALIGNED }, INT_MIN, INT_MAX, V | D, "flags" },
-{"mv4", "use four motion vectors per macroblock (MPEG-4)", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_4MV }, INT_MIN, INT_MAX, V|E, "flags"},
-{"qpel", "use 1/4-pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"},
-{"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"},
-{"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"},
-#if FF_API_GMC
-{"gmc", "use gmc", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_GMC }, INT_MIN, INT_MAX, V|E, "flags"},
-#endif
-#if FF_API_MV0
-{"mv0", "always try a mb with mv=<0,0>", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_MV0 }, INT_MIN, INT_MAX, V|E, "flags"},
-#endif
-#if FF_API_INPUT_PRESERVED
-{"input_preserved", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_INPUT_PRESERVED }, INT_MIN, INT_MAX, 0, "flags"},
-#endif
-{"pass1", "use internal 2-pass ratecontrol in first  pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"},
-{"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"},
-{"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"},
-#if FF_API_EMU_EDGE
-{"emu_edge", "do not draw edges", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_EMU_EDGE }, INT_MIN, INT_MAX, 0, "flags"},
-#endif
-{"psnr", "error[?] variables will be set during encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PSNR }, INT_MIN, INT_MAX, V|E, "flags"},
-{"truncated", "Input bitstream might be randomly truncated", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_TRUNCATED }, INT_MIN, INT_MAX, V|D, "flags"},
-#if FF_API_NORMALIZE_AQP
-{"naq", "normalize adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_NORMALIZE_AQP }, INT_MIN, INT_MAX, V|E, "flags"},
-#endif
-{"ildct", "use interlaced DCT", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_INTERLACED_DCT }, INT_MIN, INT_MAX, V|E, "flags"},
-{"low_delay", "force low delay", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOW_DELAY }, INT_MIN, INT_MAX, V|D|E, "flags"},
-{"global_header", "place global headers in extradata instead of every keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GLOBAL_HEADER }, INT_MIN, INT_MAX, V|A|E, "flags"},
-{"bitexact", "use only bitexact functions (except (I)DCT)", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_BITEXACT }, INT_MIN, INT_MAX, A|V|S|D|E, "flags"},
-{"aic", "H.263 advanced intra coding / MPEG-4 AC prediction", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_AC_PRED }, INT_MIN, INT_MAX, V|E, "flags"},
-{"ilme", "interlaced motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_INTERLACED_ME }, INT_MIN, INT_MAX, V|E, "flags"},
-{"cgop", "closed GOP", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_CLOSED_GOP }, INT_MIN, INT_MAX, V|E, "flags"},
-{"output_corrupt", "Output even potentially corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_OUTPUT_CORRUPT }, INT_MIN, INT_MAX, V|D, "flags"},
-{"fast", "allow non-spec-compliant speedup tricks", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_FAST }, INT_MIN, INT_MAX, V|E, "flags2"},
-{"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"},
-{"ignorecrop", "ignore cropping information from sps", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_IGNORE_CROP }, INT_MIN, INT_MAX, V|D, "flags2"},
-{"local_header", "place global headers at every keyframe instead of in extradata", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_LOCAL_HEADER }, INT_MIN, INT_MAX, V|E, "flags2"},
-{"chunks", "Frame data might be split into multiple chunks", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_CHUNKS }, INT_MIN, INT_MAX, V|D, "flags2"},
-{"showall", "Show all frames before the first keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_SHOW_ALL }, INT_MIN, INT_MAX, V|D, "flags2"},
-{"export_mvs", "export motion vectors through frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_EXPORT_MVS}, INT_MIN, INT_MAX, V|D, "flags2"},
-{"skip_manual", "do not skip samples and export skip information as frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_SKIP_MANUAL}, INT_MIN, INT_MAX, V|D, "flags2"},
-{"ass_ro_flush_noop", "do not reset ASS ReadOrder field on flush", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_RO_FLUSH_NOOP}, INT_MIN, INT_MAX, S|D, "flags2"},
-#if FF_API_MOTION_EST
-{"me_method", "set motion estimation method", OFFSET(me_method), AV_OPT_TYPE_INT, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method"},
-{"zero", "zero motion estimation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_ZERO }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"full", "full motion estimation (slowest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_FULL }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"epzs", "EPZS motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"esa", "esa motion estimation (alias for full)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_FULL }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"tesa", "tesa motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_TESA }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"dia", "diamond motion estimation (alias for EPZS)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"log", "log motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_LOG }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"phods", "phods motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_PHODS }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"x1", "X1 motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_X1 }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"hex", "hex motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_HEX }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"umh", "umh motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_UMH }, INT_MIN, INT_MAX, V|E, "me_method" },
-{"iter", "iter motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_ITER }, INT_MIN, INT_MAX, V|E, "me_method" },
-#endif
-{"time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, INT_MIN, INT_MAX},
-{"g", "set the group of picture (GOP) size", OFFSET(gop_size), AV_OPT_TYPE_INT, {.i64 = 12 }, INT_MIN, INT_MAX, V|E},
-{"ar", "set audio sampling rate (in Hz)", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D|E},
-{"ac", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D|E},
-{"cutoff", "set cutoff bandwidth", OFFSET(cutoff), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|E},
-{"frame_size", NULL, OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|E},
-{"frame_number", NULL, OFFSET(frame_number), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"delay", NULL, OFFSET(delay), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"qcomp", "video quantizer scale compression (VBR). Constant of ratecontrol equation. "
-          "Recommended range for default rc_eq: 0.0-1.0",
-          OFFSET(qcompress), AV_OPT_TYPE_FLOAT, {.dbl = 0.5 }, -FLT_MAX, FLT_MAX, V|E},
-{"qblur", "video quantizer scale blur (VBR)", OFFSET(qblur), AV_OPT_TYPE_FLOAT, {.dbl = 0.5 }, -1, FLT_MAX, V|E},
-{"qmin", "minimum video quantizer scale (VBR)", OFFSET(qmin), AV_OPT_TYPE_INT, {.i64 = 2 }, -1, 69, V|E},
-{"qmax", "maximum video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.i64 = 31 }, -1, 1024, V|E},
-{"qdiff", "maximum difference between the quantizer scales (VBR)", OFFSET(max_qdiff), AV_OPT_TYPE_INT, {.i64 = 3 }, INT_MIN, INT_MAX, V|E},
-{"bf", "set maximum number of B-frames between non-B-frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, -1, INT_MAX, V|E},
-{"b_qfactor", "QP factor between P- and B-frames", OFFSET(b_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E},
-#if FF_API_RC_STRATEGY
-{"rc_strategy", "ratecontrol method", OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-#if FF_API_PRIVATE_OPT
-{"b_strategy", "strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, V|E},
-{"ps", "RTP payload size in bytes", OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-#if FF_API_STAT_BITS
-{"mv_bits", NULL, OFFSET(mv_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"header_bits", NULL, OFFSET(header_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"i_tex_bits", NULL, OFFSET(i_tex_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"p_tex_bits", NULL, OFFSET(p_tex_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"i_count", NULL, OFFSET(i_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"p_count", NULL, OFFSET(p_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"skip_count", NULL, OFFSET(skip_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"misc_bits", NULL, OFFSET(misc_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"frame_bits", NULL, OFFSET(frame_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-#endif
-{"codec_tag", NULL, OFFSET(codec_tag), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"bug", "work around not autodetected encoder bugs", OFFSET(workaround_bugs), AV_OPT_TYPE_FLAGS, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"},
-{"autodetect", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"},
-#if FF_API_OLD_MSMPEG4
-{"old_msmpeg4", "some old lavc-generated MSMPEG4v3 files (no autodetection)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_OLD_MSMPEG4 }, INT_MIN, INT_MAX, V|D, "bug"},
-#endif
-{"xvid_ilace", "Xvid interlacing bug (autodetected if FOURCC == XVIX)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_XVID_ILACE }, INT_MIN, INT_MAX, V|D, "bug"},
-{"ump4", "(autodetected if FOURCC == UMP4)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_UMP4 }, INT_MIN, INT_MAX, V|D, "bug"},
-{"no_padding", "padding bug (autodetected)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_NO_PADDING }, INT_MIN, INT_MAX, V|D, "bug"},
-{"amv", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AMV }, INT_MIN, INT_MAX, V|D, "bug"},
-#if FF_API_AC_VLC
-{"ac_vlc", "illegal VLC bug (autodetected per FOURCC)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AC_VLC }, INT_MIN, INT_MAX, V|D, "bug"},
-#endif
-{"qpel_chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_QPEL_CHROMA }, INT_MIN, INT_MAX, V|D, "bug"},
-{"std_qpel", "old standard qpel (autodetected per FOURCC/version)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_STD_QPEL }, INT_MIN, INT_MAX, V|D, "bug"},
-{"qpel_chroma2", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_QPEL_CHROMA2 }, INT_MIN, INT_MAX, V|D, "bug"},
-{"direct_blocksize", "direct-qpel-blocksize bug (autodetected per FOURCC/version)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_DIRECT_BLOCKSIZE }, INT_MIN, INT_MAX, V|D, "bug"},
-{"edge", "edge padding bug (autodetected per FOURCC/version)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_EDGE }, INT_MIN, INT_MAX, V|D, "bug"},
-{"hpel_chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_HPEL_CHROMA }, INT_MIN, INT_MAX, V|D, "bug"},
-{"dc_clip", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_DC_CLIP }, INT_MIN, INT_MAX, V|D, "bug"},
-{"ms", "work around various bugs in Microsoft's broken decoders", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_MS }, INT_MIN, INT_MAX, V|D, "bug"},
-{"trunc", "truncated frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_TRUNCATED}, INT_MIN, INT_MAX, V|D, "bug"},
-{"strict", "how strictly to follow the standards", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
-{"very", "strictly conform to a older more strict version of the spec or reference software", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_VERY_STRICT }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
-{"strict", "strictly conform to all the things in the spec no matter what the consequences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_STRICT }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
-{"normal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_NORMAL }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
-{"unofficial", "allow unofficial extensions", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_UNOFFICIAL }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
-{"experimental", "allow non-standardized experimental things", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
-{"b_qoffset", "QP offset between P- and B-frames", OFFSET(b_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E},
-{"err_detect", "set error detection flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
-{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
-{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
-{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
-{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
-{"ignore_err", "ignore errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_IGNORE_ERR }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
-{"careful",    "consider things that violate the spec, are fast to check and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
-{"compliant",  "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
-{"aggressive", "consider things that a sane encoder should not do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
-{"has_b_frames", NULL, OFFSET(has_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"block_align", NULL, OFFSET(block_align), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-#if FF_API_PRIVATE_OPT
-{"mpeg_quant", "use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-#if FF_API_MPV_OPT
-{"qsquish", "deprecated, use encoder private options instead", OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, 0, 99, V|E},
-{"rc_qmod_amp",  "deprecated, use encoder private options instead", OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E},
-{"rc_qmod_freq", "deprecated, use encoder private options instead", OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-{"rc_override_count", NULL, OFFSET(rc_override_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-#if FF_API_MPV_OPT
-{"rc_eq", "deprecated, use encoder private options instead", OFFSET(rc_eq), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, V|E},
-#endif
-{"maxrate", "maximum bitrate (in bits/s). Used for VBV together with bufsize.", OFFSET(rc_max_rate), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, 0, INT_MAX, V|A|E},
-{"minrate", "minimum bitrate (in bits/s). Most useful in setting up a CBR encode. It is of little use otherwise.",
-            OFFSET(rc_min_rate), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
-{"bufsize", "set ratecontrol buffer size (in bits)", OFFSET(rc_buffer_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|V|E},
-#if FF_API_MPV_OPT
-{"rc_buf_aggressivity", "deprecated, use encoder private options instead", OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, V|E},
-#endif
-{"i_qfactor", "QP factor between P- and I-frames", OFFSET(i_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = -0.8 }, -FLT_MAX, FLT_MAX, V|E},
-{"i_qoffset", "QP offset between P- and I-frames", OFFSET(i_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, -FLT_MAX, FLT_MAX, V|E},
-#if FF_API_MPV_OPT
-{"rc_init_cplx", "deprecated, use encoder private options instead", OFFSET(rc_initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E},
-#endif
-{"dct", "DCT algorithm", OFFSET(dct_algo), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|E, "dct"},
-{"auto", "autoselect a good one", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_AUTO }, INT_MIN, INT_MAX, V|E, "dct"},
-{"fastint", "fast integer", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FASTINT }, INT_MIN, INT_MAX, V|E, "dct"},
-{"int", "accurate integer", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_INT }, INT_MIN, INT_MAX, V|E, "dct"},
-{"mmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_MMX }, INT_MIN, INT_MAX, V|E, "dct"},
-{"altivec", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_ALTIVEC }, INT_MIN, INT_MAX, V|E, "dct"},
-{"faan", "floating point AAN DCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FAAN }, INT_MIN, INT_MAX, V|E, "dct"},
-{"lumi_mask", "compresses bright areas stronger than medium ones", OFFSET(lumi_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E},
-{"tcplx_mask", "temporal complexity masking", OFFSET(temporal_cplx_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E},
-{"scplx_mask", "spatial complexity masking", OFFSET(spatial_cplx_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E},
-{"p_mask", "inter masking", OFFSET(p_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E},
-{"dark_mask", "compresses dark areas stronger than medium ones", OFFSET(dark_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E},
-{"idct", "select IDCT implementation", OFFSET(idct_algo), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|E|D, "idct"},
-{"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_AUTO }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"int", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_INT }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simple", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLE }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simplemmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEMMX }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"arm", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ARM }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"altivec", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ALTIVEC }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#if FF_API_ARCH_SH4
-{"sh4", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SH4 }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#endif
-{"simplearm", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARM }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simplearmv5te", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV5TE }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simplearmv6", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV6 }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"simpleneon", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLENEON }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#if FF_API_ARCH_ALPHA
-{"simplealpha", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEALPHA }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#endif
-#if FF_API_UNUSED_MEMBERS
-{"ipp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_IPP }, INT_MIN, INT_MAX, V|E|D, "idct"},
-#endif /* FF_API_UNUSED_MEMBERS */
-{"xvid", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"xvidmmx", "deprecated, for compatibility only", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"faani", "floating point AAN IDCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_FAAN }, INT_MIN, INT_MAX, V|D|E, "idct"},
-{"simpleauto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEAUTO }, INT_MIN, INT_MAX, V|E|D, "idct"},
-{"slice_count", NULL, OFFSET(slice_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"ec", "set error concealment strategy", OFFSET(error_concealment), AV_OPT_TYPE_FLAGS, {.i64 = 3 }, INT_MIN, INT_MAX, V|D, "ec"},
-{"guess_mvs", "iterative motion vector (MV) search (slow)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_GUESS_MVS }, INT_MIN, INT_MAX, V|D, "ec"},
-{"deblock", "use strong deblock filter for damaged MBs", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_DEBLOCK }, INT_MIN, INT_MAX, V|D, "ec"},
-{"favor_inter", "favor predicting from the previous frame", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_FAVOR_INTER }, INT_MIN, INT_MAX, V|D, "ec"},
-{"bits_per_coded_sample", NULL, OFFSET(bits_per_coded_sample), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-#if FF_API_PRIVATE_OPT
-{"pred", "prediction method", OFFSET(prediction_method), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "pred"},
-{"left", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_LEFT }, INT_MIN, INT_MAX, V|E, "pred"},
-{"plane", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_PLANE }, INT_MIN, INT_MAX, V|E, "pred"},
-{"median", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_MEDIAN }, INT_MIN, INT_MAX, V|E, "pred"},
-#endif
-{"aspect", "sample aspect ratio", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10, V|E},
-{"sar",    "sample aspect ratio", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10, V|E},
-{"debug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, V|A|S|E|D, "debug"},
-{"pict", "picture info", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_PICT_INFO }, INT_MIN, INT_MAX, V|D, "debug"},
-{"rc", "rate control", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_RC }, INT_MIN, INT_MAX, V|E, "debug"},
-{"bitstream", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BITSTREAM }, INT_MIN, INT_MAX, V|D, "debug"},
-{"mb_type", "macroblock (MB) type", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MB_TYPE }, INT_MIN, INT_MAX, V|D, "debug"},
-{"qp", "per-block quantization parameter (QP)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_QP }, INT_MIN, INT_MAX, V|D, "debug"},
-#if FF_API_DEBUG_MV
-{"mv", "motion vector", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MV }, INT_MIN, INT_MAX, V|D, "debug"},
-#endif
-{"dct_coeff", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_DCT_COEFF }, INT_MIN, INT_MAX, V|D, "debug"},
-{"green_metadata", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_GREEN_MD }, INT_MIN, INT_MAX, V|D, "debug"},
-{"skip", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_SKIP }, INT_MIN, INT_MAX, V|D, "debug"},
-{"startcode", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_STARTCODE }, INT_MIN, INT_MAX, V|D, "debug"},
-#if FF_API_UNUSED_MEMBERS
-{"pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_PTS }, INT_MIN, INT_MAX, V|D, "debug"},
-#endif /* FF_API_UNUSED_MEMBERS */
-{"er", "error recognition", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_ER }, INT_MIN, INT_MAX, V|D, "debug"},
-{"mmco", "memory management control operations (H.264)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MMCO }, INT_MIN, INT_MAX, V|D, "debug"},
-{"bugs", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUGS }, INT_MIN, INT_MAX, V|D, "debug"},
-{"vis_qp", "visualize quantization parameter (QP), lower QP are tinted greener", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_QP }, INT_MIN, INT_MAX, V|D, "debug"},
-{"vis_mb_type", "visualize block types", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MB_TYPE }, INT_MIN, INT_MAX, V|D, "debug"},
-{"buffers", "picture buffer allocations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUFFERS }, INT_MIN, INT_MAX, V|D, "debug"},
-{"thread_ops", "threading operations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_THREADS }, INT_MIN, INT_MAX, V|A|D, "debug"},
-{"nomc", "skip motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_NOMC }, INT_MIN, INT_MAX, V|A|D, "debug"},
-#if FF_API_VISMV
-{"vismv", "visualize motion vectors (MVs) (deprecated)", OFFSET(debug_mv), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, V|D, "debug_mv"},
-{"pf", "forward predicted MVs of P-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_P_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"},
-{"bf", "forward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"},
-{"bb", "backward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_BACK }, INT_MIN, INT_MAX, V|D, "debug_mv"},
-#endif
-{"cmp", "full-pel ME compare function", OFFSET(me_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"subcmp", "sub-pel ME compare function", OFFSET(me_sub_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"mbcmp", "macroblock compare function", OFFSET(mb_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"ildctcmp", "interlaced DCT compare function", OFFSET(ildct_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_VSAD }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"dia_size", "diamond type & size for motion estimation", OFFSET(dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-{"last_pred", "amount of motion predictors from the previous frame", OFFSET(last_predictor_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#if FF_API_PRIVATE_OPT
-{"preme", "pre motion estimation", OFFSET(pre_me), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-{"precmp", "pre motion estimation compare function", OFFSET(me_pre_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"sad", "sum of absolute differences, fast", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SAD }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"sse", "sum of squared errors", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SSE }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"satd", "sum of absolute Hadamard transformed differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SATD }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"dct", "sum of absolute DCT transformed differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCT }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"psnr", "sum of squared quantization errors (avoid, low quality)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_PSNR }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"bit", "number of bits needed for the block", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_BIT }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"rd", "rate distortion optimal, slow", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_RD }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"zero", "0", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_ZERO }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"vsad", "sum of absolute vertical differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_VSAD }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"vsse", "sum of squared vertical differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_VSSE }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"nsse", "noise preserving sum of squared differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_NSSE }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-#if CONFIG_SNOW_ENCODER
-{"w53", "5/3 wavelet, only used in snow", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_W53 }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"w97", "9/7 wavelet, only used in snow", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_W97 }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-#endif
-{"dctmax", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_CHROMA }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-{"pre_dia_size", "diamond type & size for motion estimation pre-pass", OFFSET(pre_dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-{"subq", "sub-pel motion estimation quality", OFFSET(me_subpel_quality), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E},
-#if FF_API_AFD
-{"dtg_active_format", NULL, OFFSET(dtg_active_format), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-#endif
-{"me_range", "limit motion vectors range (1023 for DivX player)", OFFSET(me_range), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#if FF_API_QUANT_BIAS
-{"ibias", "intra quant bias", OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E},
-{"pbias", "inter quant bias", OFFSET(inter_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E},
-#endif
-{"global_quality", NULL, OFFSET(global_quality), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
-#if FF_API_CODER_TYPE
-{"coder", NULL, OFFSET(coder_type), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "coder"},
-{"vlc", "variable length coder / Huffman coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_VLC }, INT_MIN, INT_MAX, V|E, "coder"},
-{"ac", "arithmetic coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_AC }, INT_MIN, INT_MAX, V|E, "coder"},
-{"raw", "raw (no encoding)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_RAW }, INT_MIN, INT_MAX, V|E, "coder"},
-{"rle", "run-length coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_RLE }, INT_MIN, INT_MAX, V|E, "coder"},
-#if FF_API_UNUSED_MEMBERS
-{"deflate", "deflate-based coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_DEFLATE }, INT_MIN, INT_MAX, V|E, "coder"},
-#endif /* FF_API_UNUSED_MEMBERS */
-#endif /* FF_API_CODER_TYPE */
-#if FF_API_PRIVATE_OPT
-{"context", "context model", OFFSET(context_model), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-{"slice_flags", NULL, OFFSET(slice_flags), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-#if FF_API_XVMC
-{"xvmc_acceleration", NULL, OFFSET(xvmc_acceleration), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-#endif /* FF_API_XVMC */
-{"mbd", "macroblock decision algorithm (high quality mode)", OFFSET(mb_decision), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, 2, V|E, "mbd"},
-{"simple", "use mbcmp", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_SIMPLE }, INT_MIN, INT_MAX, V|E, "mbd"},
-{"bits", "use fewest bits", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_BITS }, INT_MIN, INT_MAX, V|E, "mbd"},
-{"rd", "use best rate distortion", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_RD }, INT_MIN, INT_MAX, V|E, "mbd"},
-#if FF_API_STREAM_CODEC_TAG
-{"stream_codec_tag", NULL, OFFSET(stream_codec_tag), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-#endif
-#if FF_API_PRIVATE_OPT
-{"sc_threshold", "scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-#if FF_API_MPV_OPT
-{"lmin", "deprecated, use encoder private options instead", OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 =  0 }, 0, INT_MAX, V|E},
-{"lmax", "deprecated, use encoder private options instead", OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 =  0 }, 0, INT_MAX, V|E},
-#endif
-#if FF_API_PRIVATE_OPT
-{"nr", "noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-{"rc_init_occupancy", "number of bits which should be loaded into the rc buffer before decoding starts", OFFSET(rc_initial_buffer_occupancy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-{"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"},
-#if FF_API_ERROR_RATE
-{"error", NULL, OFFSET(error_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-{"threads", "set the number of threads", OFFSET(thread_count), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, INT_MAX, V|A|E|D, "threads"},
-{"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, V|E|D, "threads"},
-#if FF_API_MPV_OPT
-{"me_threshold", "motion estimation threshold", OFFSET(me_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-{"mb_threshold", "macroblock threshold", OFFSET(mb_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-{"dc", "intra_dc_precision", OFFSET(intra_dc_precision), AV_OPT_TYPE_INT, {.i64 = 0 }, -8, 16, V|E},
-{"nssew", "nsse weight", OFFSET(nsse_weight), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E},
-{"skip_top", "number of macroblock rows at the top which are skipped", OFFSET(skip_top), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D},
-{"skip_bottom", "number of macroblock rows at the bottom which are skipped", OFFSET(skip_bottom), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D},
-{"profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT, {.i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "profile"},
-{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "profile"},
-{"aac_main", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_MAIN }, INT_MIN, INT_MAX, A|E, "profile"},
-{"aac_low", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_LOW }, INT_MIN, INT_MAX, A|E, "profile"},
-{"aac_ssr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_SSR }, INT_MIN, INT_MAX, A|E, "profile"},
-{"aac_ltp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_LTP }, INT_MIN, INT_MAX, A|E, "profile"},
-{"aac_he", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_HE }, INT_MIN, INT_MAX, A|E, "profile"},
-{"aac_he_v2", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_HE_V2 }, INT_MIN, INT_MAX, A|E, "profile"},
-{"aac_ld", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_LD }, INT_MIN, INT_MAX, A|E, "profile"},
-{"aac_eld", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_ELD }, INT_MIN, INT_MAX, A|E, "profile"},
-{"mpeg2_aac_low", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG2_AAC_LOW }, INT_MIN, INT_MAX, A|E, "profile"},
-{"mpeg2_aac_he", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG2_AAC_HE }, INT_MIN, INT_MAX, A|E, "profile"},
-{"dts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS }, INT_MIN, INT_MAX, A|E, "profile"},
-{"dts_es", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_ES }, INT_MIN, INT_MAX, A|E, "profile"},
-{"dts_96_24", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_96_24 }, INT_MIN, INT_MAX, A|E, "profile"},
-{"dts_hd_hra", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_HRA }, INT_MIN, INT_MAX, A|E, "profile"},
-{"dts_hd_ma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_MA }, INT_MIN, INT_MAX, A|E, "profile"},
-{"mpeg4_sp",   NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_SIMPLE }, INT_MIN, INT_MAX, V|E, "profile"},
-{"mpeg4_core", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_CORE }, INT_MIN, INT_MAX, V|E, "profile"},
-{"mpeg4_main", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_MAIN }, INT_MIN, INT_MAX, V|E, "profile"},
-{"mpeg4_asp",  NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_ADVANCED_SIMPLE }, INT_MIN, INT_MAX, V|E, "profile"},
-{"level", NULL, OFFSET(level), AV_OPT_TYPE_INT, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"},
-{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"},
-{"lowres", "decode at 1= 1/2, 2=1/4, 3=1/8 resolutions", OFFSET(lowres), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|A|D},
-#if FF_API_PRIVATE_OPT
-{"skip_threshold", "frame skip threshold", OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-{"skip_factor", "frame skip factor", OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-{"skip_exp", "frame skip exponent", OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-{"skipcmp", "frame skip compare function", OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, V|E, "cmp_func"},
-#endif
-#if FF_API_MPV_OPT
-{"border_mask", "deprecated, use encoder private options instead", OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E},
-#endif
-{"mblmin", "minimum macroblock Lagrange factor (VBR)", OFFSET(mb_lmin), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 2 }, 1, FF_LAMBDA_MAX, V|E},
-{"mblmax", "maximum macroblock Lagrange factor (VBR)", OFFSET(mb_lmax), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 31 }, 1, FF_LAMBDA_MAX, V|E},
-#if FF_API_PRIVATE_OPT
-{"mepc", "motion estimation bitrate penalty compensation (1.0 = 256)", OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, V|E},
-#endif
-{"skip_loop_filter", "skip loop filtering process for the selected frames", OFFSET(skip_loop_filter), AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"skip_idct"       , "skip IDCT/dequantization for the selected frames",    OFFSET(skip_idct),        AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"skip_frame"      , "skip decoding for the selected frames",               OFFSET(skip_frame),       AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"none"            , "discard no frame",                    0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONE    }, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"default"         , "discard useless frames",              0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"noref"           , "discard all non-reference frames",    0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONREF  }, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"bidir"           , "discard all bidirectional frames",    0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_BIDIR   }, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"nokey"           , "discard all frames except keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONKEY  }, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"nointra"         , "discard all frames except I frames",  0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONINTRA}, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"all"             , "discard all frames",                  0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_ALL     }, INT_MIN, INT_MAX, V|D, "avdiscard"},
-{"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 4, V|E},
-#if FF_API_PRIVATE_OPT
-{"brd_scale", "downscale frames for dynamic B-frame decision", OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, 10, V|E},
-#endif
-{"keyint_min", "minimum interval between IDR-frames", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.i64 = 25 }, INT_MIN, INT_MAX, V|E},
-{"refs", "reference frames to consider for motion compensation", OFFSET(refs), AV_OPT_TYPE_INT, {.i64 = 1 }, INT_MIN, INT_MAX, V|E},
-#if FF_API_PRIVATE_OPT
-{"chromaoffset", "chroma QP offset from luma", OFFSET(chromaoffset), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
-#endif
-{"trellis", "rate-distortion optimal quantization", OFFSET(trellis), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
-#if FF_API_UNUSED_MEMBERS
-{"sc_factor", "multiplied by qscale for each frame and added to scene_change_score", OFFSET(scenechange_factor), AV_OPT_TYPE_INT, {.i64 = 6 }, 0, INT_MAX, V|E},
-#endif /* FF_API_UNUSED_MEMBERS */
-{"mv0_threshold", NULL, OFFSET(mv0_threshold), AV_OPT_TYPE_INT, {.i64 = 256 }, 0, INT_MAX, V|E},
-#if FF_API_PRIVATE_OPT
-{"b_sensitivity", "adjust sensitivity of b_frame_strategy 1", OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, V|E},
-#endif
-{"compression_level", NULL, OFFSET(compression_level), AV_OPT_TYPE_INT, {.i64 = FF_COMPRESSION_DEFAULT }, INT_MIN, INT_MAX, V|A|E},
-#if FF_API_PRIVATE_OPT
-{"min_prediction_order", NULL, OFFSET(min_prediction_order), AV_OPT_TYPE_INT, {.i64 = -1 }, INT_MIN, INT_MAX, A|E},
-{"max_prediction_order", NULL, OFFSET(max_prediction_order), AV_OPT_TYPE_INT, {.i64 = -1 }, INT_MIN, INT_MAX, A|E},
-{"timecode_frame_start", "GOP timecode frame start number, in non-drop-frame format", OFFSET(timecode_frame_start), AV_OPT_TYPE_INT64, {.i64 = -1 }, -1, INT64_MAX, V|E},
-#endif
-{"bits_per_raw_sample", NULL, OFFSET(bits_per_raw_sample), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
-{"channel_layout", NULL, OFFSET(channel_layout), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, 0, INT64_MAX, A|E|D, "channel_layout"},
-{"request_channel_layout", NULL, OFFSET(request_channel_layout), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, 0, INT64_MAX, A|D, "request_channel_layout"},
-{"rc_max_vbv_use", NULL, OFFSET(rc_max_available_vbv_use), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0.0, FLT_MAX, V|E},
-{"rc_min_vbv_use", NULL, OFFSET(rc_min_vbv_overflow_use),  AV_OPT_TYPE_FLOAT, {.dbl = 3 },     0.0, FLT_MAX, V|E},
-{"ticks_per_frame", NULL, OFFSET(ticks_per_frame), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, INT_MAX, A|V|E|D},
-{"color_primaries", "color primaries", OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64 = AVCOL_PRI_UNSPECIFIED }, 1, AVCOL_PRI_NB-1, V|E|D, "color_primaries_type"},
-{"bt709",       "BT.709",         0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_BT709 },        INT_MIN, INT_MAX, V|E|D, "color_primaries_type"},
-{"unspecified", "Unspecified",    0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_UNSPECIFIED },  INT_MIN, INT_MAX, V|E|D, "color_primaries_type"},
-{"bt470m",      "BT.470 M",       0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_BT470M },       INT_MIN, INT_MAX, V|E|D, "color_primaries_type"},
-{"bt470bg",     "BT.470 BG",      0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_BT470BG },      INT_MIN, INT_MAX, V|E|D, "color_primaries_type"},
-{"smpte170m",   "SMPTE 170 M",    0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE170M },    INT_MIN, INT_MAX, V|E|D, "color_primaries_type"},
-{"smpte240m",   "SMPTE 240 M",    0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE240M },    INT_MIN, INT_MAX, V|E|D, "color_primaries_type"},
-{"film",        "Film",           0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_FILM },         INT_MIN, INT_MAX, V|E|D, "color_primaries_type"},
-{"bt2020",      "BT.2020",        0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_BT2020 },       INT_MIN, INT_MAX, V|E|D, "color_primaries_type"},
-{"smpte428_1",  "SMPTE ST 428-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTEST428_1 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"},
-{"color_trc", "color transfer characteristics", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64 = AVCOL_TRC_UNSPECIFIED }, 1, AVCOL_TRC_NB-1, V|E|D, "color_trc_type"},
-{"bt709",        "BT.709",           0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT709 },        INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"unspecified",  "Unspecified",      0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_UNSPECIFIED },  INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"gamma22",      "BT.470 M",         0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_GAMMA22 },      INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"gamma28",      "BT.470 BG",        0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_GAMMA28 },      INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"smpte170m",    "SMPTE 170 M",      0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTE170M },    INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"smpte240m",    "SMPTE 240 M",      0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTE240M },    INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"linear",       "Linear",           0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LINEAR },       INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"log",          "Log",              0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LOG },          INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"log_sqrt",     "Log square root",  0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_LOG_SQRT },     INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"iec61966_2_4", "IEC 61966-2-4",    0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_IEC61966_2_4 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"bt1361",       "BT.1361",          0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT1361_ECG },   INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"iec61966_2_1", "IEC 61966-2-1",    0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_IEC61966_2_1 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"bt2020_10bit", "BT.2020 - 10 bit", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT2020_10 },    INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"bt2020_12bit", "BT.2020 - 12 bit", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT2020_12 },    INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"smpte2084",    "SMPTE ST 2084",    0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTEST2084 },  INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"smpte428_1",   "SMPTE ST 428-1",   0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTEST428_1 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"colorspace", "color space", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = AVCOL_SPC_UNSPECIFIED }, 0, AVCOL_SPC_NB-1, V|E|D, "colorspace_type"},
-{"rgb",         "RGB",         0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_RGB },         INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"bt709",       "BT.709",      0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT709 },       INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"fcc",         "FCC",         0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_FCC },         INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"bt470bg",     "BT.470 BG",   0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT470BG },     INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"smpte170m",   "SMPTE 170 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE170M },   INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"smpte240m",   "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE240M },   INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"ycocg",       "YCOCG",       0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_YCOCG },       INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"bt2020_ncl",  "BT.2020 NCL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_NCL },  INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"bt2020_cl",   "BT.2020 CL",  0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_CL },   INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
-{"color_range", "color range", OFFSET(color_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, AVCOL_RANGE_NB-1, V|E|D, "color_range_type"},
-{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_range_type"},
-{"mpeg", "MPEG (219*2^(n-8))", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG },        INT_MIN, INT_MAX, V|E|D, "color_range_type"},
-{"jpeg", "JPEG (2^n-1)",       0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG },        INT_MIN, INT_MAX, V|E|D, "color_range_type"},
-{"chroma_sample_location", "chroma sample location", OFFSET(chroma_sample_location), AV_OPT_TYPE_INT, {.i64 = AVCHROMA_LOC_UNSPECIFIED }, 0, AVCHROMA_LOC_NB-1, V|E|D, "chroma_sample_location_type"},
-{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
-{"left",        "Left",        0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_LEFT },        INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
-{"center",      "Center",      0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_CENTER },      INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
-{"topleft",     "Top-left",    0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_TOPLEFT },     INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
-{"top",         "Top",         0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_TOP },         INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
-{"bottomleft",  "Bottom-left", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_BOTTOMLEFT },  INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
-{"bottom",      "Bottom",      0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_BOTTOM },      INT_MIN, INT_MAX, V|E|D, "chroma_sample_location_type"},
-{"log_level_offset", "set the log level offset", OFFSET(log_level_offset), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX },
-{"slices", "set the number of slices, used in parallelized encoding", OFFSET(slices), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|E},
-{"thread_type", "select multithreading type", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, {.i64 = FF_THREAD_SLICE|FF_THREAD_FRAME }, 0, INT_MAX, V|A|E|D, "thread_type"},
-{"slice", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_THREAD_SLICE }, INT_MIN, INT_MAX, V|E|D, "thread_type"},
-{"frame", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_THREAD_FRAME }, INT_MIN, INT_MAX, V|E|D, "thread_type"},
-{"audio_service_type", "audio service type", OFFSET(audio_service_type), AV_OPT_TYPE_INT, {.i64 = AV_AUDIO_SERVICE_TYPE_MAIN }, 0, AV_AUDIO_SERVICE_TYPE_NB-1, A|E, "audio_service_type"},
-{"ma", "Main Audio Service", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_MAIN },              INT_MIN, INT_MAX, A|E, "audio_service_type"},
-{"ef", "Effects",            0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_EFFECTS },           INT_MIN, INT_MAX, A|E, "audio_service_type"},
-{"vi", "Visually Impaired",  0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED }, INT_MIN, INT_MAX, A|E, "audio_service_type"},
-{"hi", "Hearing Impaired",   0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED },  INT_MIN, INT_MAX, A|E, "audio_service_type"},
-{"di", "Dialogue",           0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_DIALOGUE },          INT_MIN, INT_MAX, A|E, "audio_service_type"},
-{"co", "Commentary",         0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_COMMENTARY },        INT_MIN, INT_MAX, A|E, "audio_service_type"},
-{"em", "Emergency",          0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_EMERGENCY },         INT_MIN, INT_MAX, A|E, "audio_service_type"},
-{"vo", "Voice Over",         0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_VOICE_OVER },        INT_MIN, INT_MAX, A|E, "audio_service_type"},
-{"ka", "Karaoke",            0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_KARAOKE },           INT_MIN, INT_MAX, A|E, "audio_service_type"},
-{"request_sample_fmt", "sample format audio decoders should prefer", OFFSET(request_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64=AV_SAMPLE_FMT_NONE}, -1, INT_MAX, A|D, "request_sample_fmt"},
-{"pkt_timebase", NULL, OFFSET(pkt_timebase), AV_OPT_TYPE_RATIONAL, {.dbl = 0 }, 0, INT_MAX, 0},
-{"sub_charenc", "set input text subtitles character encoding", OFFSET(sub_charenc), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, S|D},
-{"sub_charenc_mode", "set input text subtitles character encoding mode", OFFSET(sub_charenc_mode), AV_OPT_TYPE_FLAGS, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC}, -1, INT_MAX, S|D, "sub_charenc_mode"},
-{"do_nothing",  NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_DO_NOTHING},  INT_MIN, INT_MAX, S|D, "sub_charenc_mode"},
-{"auto",        NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC},   INT_MIN, INT_MAX, S|D, "sub_charenc_mode"},
-{"pre_decoder", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_PRE_DECODER}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"},
-#if FF_API_ASS_TIMING
-{"sub_text_format", "set decoded text subtitle format", OFFSET(sub_text_format), AV_OPT_TYPE_INT, {.i64 = FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS}, 0, 1, S|D, "sub_text_format"},
-#else
-{"sub_text_format", "set decoded text subtitle format", OFFSET(sub_text_format), AV_OPT_TYPE_INT, {.i64 = FF_SUB_TEXT_FMT_ASS}, 0, 1, S|D, "sub_text_format"},
-#endif
-{"ass",              NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_TEXT_FMT_ASS},              INT_MIN, INT_MAX, S|D, "sub_text_format"},
-#if FF_API_ASS_TIMING
-{"ass_with_timings", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS}, INT_MIN, INT_MAX, S|D, "sub_text_format"},
-#endif
-{"refcounted_frames", NULL, OFFSET(refcounted_frames), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, A|V|D },
-#if FF_API_SIDEDATA_ONLY_PKT
-{"side_data_only_packets", NULL, OFFSET(side_data_only_packets), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, A|V|E },
-#endif
-{"skip_alpha", "Skip processing alpha", OFFSET(skip_alpha), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, V|D },
-{"field_order", "Field order", OFFSET(field_order), AV_OPT_TYPE_INT, {.i64 = AV_FIELD_UNKNOWN }, 0, 5, V|D|E, "field_order" },
-{"progressive", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_PROGRESSIVE }, 0, 0, V|D|E, "field_order" },
-{"tt", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_TT }, 0, 0, V|D|E, "field_order" },
-{"bb", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_BB }, 0, 0, V|D|E, "field_order" },
-{"tb", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_TB }, 0, 0, V|D|E, "field_order" },
-{"bt", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_BT }, 0, 0, V|D|E, "field_order" },
-{"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, A|V|S|D|E},
-{"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, A|V|S|D },
-{"pixel_format", "set pixel format", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64=AV_PIX_FMT_NONE}, -1, INT_MAX, 0 },
-{"video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str=NULL}, 0, INT_MAX, 0 },
-{NULL},
-};
-
-#undef A
-#undef V
-#undef S
-#undef E
-#undef D
-#undef DEFAULT
-#undef OFFSET
-
-#endif /* AVCODEC_OPTIONS_TABLE_H */
--- a/media/ffvpx/libavutil/dummy_funcs.c
+++ b/media/ffvpx/libavutil/dummy_funcs.c
@@ -1,19 +1,81 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "avutil.h"
+#include "opt.h"
 
 // cpu_internal.c
 int ff_get_cpu_flags_aarch64(void) { return 0; }
 int ff_get_cpu_flags_arm(void) { return 0; }
 int ff_get_cpu_flags_ppc(void) { return 0; }
 
 // float_dsp.c
 #include "float_dsp.h"
 void ff_float_dsp_init_aarch64(AVFloatDSPContext *fdsp) {}
 void ff_float_dsp_init_arm(AVFloatDSPContext *fdsp) {}
 void ff_float_dsp_init_ppc(AVFloatDSPContext *fdsp, int strict) {}
 void ff_float_dsp_init_mips(AVFloatDSPContext *fdsp) {}
+
+// opt.c
+int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags) { return 0; }
+void av_opt_set_defaults(void *s) {}
+void av_opt_set_defaults2(void *s, int mask, int flags) {}
+int av_set_options_string(void *ctx, const char *opts,
+                          const char *key_val_sep, const char *pairs_sep) { return 0; }
+int av_opt_set_from_string(void *ctx, const char *opts,
+                           const char *const *shorthand,
+                           const char *key_val_sep, const char *pairs_sep) { return 0; }
+void av_opt_free(void *obj) {}
+int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name) { return 0; }
+int av_opt_set_dict(void *obj, struct AVDictionary **options) { return 0; }
+int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags) { return 0; }
+int av_opt_get_key_value(const char **ropts,
+                         const char *key_val_sep, const char *pairs_sep,
+                         unsigned flags,
+                         char **rkey, char **rval) { return 0; }
+int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int       *flags_out) { return 0; }
+int av_opt_eval_int   (void *obj, const AVOption *o, const char *val, int       *int_out) { return 0; }
+int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t   *int64_out) { return 0; }
+int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float     *float_out) { return 0; }
+int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double    *double_out) { return 0; }
+int av_opt_eval_q     (void *obj, const AVOption *o, const char *val, AVRational *q_out) { return 0; }
+const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
+                            int opt_flags, int search_flags) { return 0; }
+const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
+                             int opt_flags, int search_flags, void **target_obj) { return 0; }
+const AVOption *av_opt_next(const void *obj, const AVOption *prev) { return 0; }
+void *av_opt_child_next(void *obj, void *prev) { return 0; }
+const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev) { return 0; }
+int av_opt_set         (void *obj, const char *name, const char *val, int search_flags) { return 0; }
+int av_opt_set_int     (void *obj, const char *name, int64_t     val, int search_flags) { return 0; }
+int av_opt_set_double  (void *obj, const char *name, double      val, int search_flags) { return 0; }
+int av_opt_set_q       (void *obj, const char *name, AVRational  val, int search_flags) { return 0; }
+int av_opt_set_bin     (void *obj, const char *name, const uint8_t *val, int size, int search_flags) { return 0; }
+int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags) { return 0; }
+int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags) { return 0; }
+int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags) { return 0; }
+int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags) { return 0; }
+int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags) { return 0; }
+int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags) { return 0; }
+int av_opt_get         (void *obj, const char *name, int search_flags, uint8_t **out_val) { return 0; }
+int av_opt_get_int     (void *obj, const char *name, int search_flags, int64_t *out_val) { return 0; }
+int av_opt_get_double  (void *obj, const char *name, int search_flags, double *out_val) { return 0; }
+int av_opt_get_q       (void *obj, const char *name, int search_flags, AVRational *out_val) { return 0; }
+int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out) { return 0; }
+int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt) { return 0; }
+int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt) { return 0; }
+int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val) { return 0; }
+int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout) { return 0; }
+int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val) { return 0; }
+void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name) { return 0; }
+void av_opt_freep_ranges(AVOptionRanges **ranges) {}
+int av_opt_query_ranges(AVOptionRanges **b, void *obj, const char *key, int flags) { return 0; }
+int av_opt_copy(void *dest, const void *src) { return 0; }
+int av_opt_query_ranges_default(AVOptionRanges **b, void *obj, const char *key, int flags) { return 0; }
+int av_opt_is_set_to_default(void *obj, const AVOption *o) { return 0; }
+int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags) { return 0; }
+int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
+                     const char key_val_sep, const char pairs_sep) { return 0; }
--- a/media/ffvpx/libavutil/moz.build
+++ b/media/ffvpx/libavutil/moz.build
@@ -33,17 +33,16 @@ SOURCES += [
     'imgutils.c',
     'integer.c',
     'intmath.c',
     'lls.c',
     'log.c',
     'log2_tab.c',
     'mathematics.c',
     'mem.c',
-    'opt.c',
     'parseutils.c',
     'pixdesc.c',
     'pixelutils.c',
     'rational.c',
     'reverse.c',
     'samplefmt.c',
     'threadmessage.c',
     'time.c',
deleted file mode 100644
--- a/media/ffvpx/libavutil/opt.c
+++ /dev/null
@@ -1,1994 +0,0 @@
-/*
- * AVOptions
- * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file
- * AVOptions
- * @author Michael Niedermayer <michaelni@gmx.at>
- */
-
-#include "avutil.h"
-#include "avassert.h"
-#include "avstring.h"
-#include "channel_layout.h"
-#include "common.h"
-#include "dict.h"
-#include "eval.h"
-#include "log.h"
-#include "parseutils.h"
-#include "pixdesc.h"
-#include "mathematics.h"
-#include "opt.h"
-#include "samplefmt.h"
-#include "bprint.h"
-
-#include <float.h>
-
-const AVOption *av_opt_next(const void *obj, const AVOption *last)
-{
-    const AVClass *class;
-    if (!obj)
-        return NULL;
-    class = *(const AVClass**)obj;
-    if (!last && class && class->option && class->option[0].name)
-        return class->option;
-    if (last && last[1].name)
-        return ++last;
-    return NULL;
-}
-
-static int read_number(const AVOption *o, const void *dst, double *num, int *den, int64_t *intnum)
-{
-    switch (o->type) {
-    case AV_OPT_TYPE_FLAGS:
-        *intnum = *(unsigned int*)dst;
-        return 0;
-    case AV_OPT_TYPE_PIXEL_FMT:
-        *intnum = *(enum AVPixelFormat *)dst;
-        return 0;
-    case AV_OPT_TYPE_SAMPLE_FMT:
-        *intnum = *(enum AVSampleFormat *)dst;
-        return 0;
-    case AV_OPT_TYPE_BOOL:
-    case AV_OPT_TYPE_INT:
-        *intnum = *(int *)dst;
-        return 0;
-    case AV_OPT_TYPE_CHANNEL_LAYOUT:
-    case AV_OPT_TYPE_DURATION:
-    case AV_OPT_TYPE_INT64:
-        *intnum = *(int64_t *)dst;
-        return 0;
-    case AV_OPT_TYPE_FLOAT:
-        *num = *(float *)dst;
-        return 0;
-    case AV_OPT_TYPE_DOUBLE:
-        *num = *(double *)dst;
-        return 0;
-    case AV_OPT_TYPE_RATIONAL:
-        *intnum = ((AVRational *)dst)->num;
-        *den    = ((AVRational *)dst)->den;
-        return 0;
-    case AV_OPT_TYPE_CONST:
-        *num = o->default_val.dbl;
-        return 0;
-    }
-    return AVERROR(EINVAL);
-}
-
-static int write_number(void *obj, const AVOption *o, void *dst, double num, int den, int64_t intnum)
-{
-    if (o->type != AV_OPT_TYPE_FLAGS &&
-        (o->max * den < num * intnum || o->min * den > num * intnum)) {
-        num = den ? num * intnum / den : (num * intnum ? INFINITY : NAN);
-        av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range [%g - %g]\n",
-               num, o->name, o->min, o->max);
-        return AVERROR(ERANGE);
-    }
-    if (o->type == AV_OPT_TYPE_FLAGS) {
-        double d = num*intnum/den;
-        if (d < -1.5 || d > 0xFFFFFFFF+0.5 || (llrint(d*256) & 255)) {
-            av_log(obj, AV_LOG_ERROR,
-                   "Value %f for parameter '%s' is not a valid set of 32bit integer flags\n",
-                   num*intnum/den, o->name);
-            return AVERROR(ERANGE);
-        }
-    }
-
-    switch (o->type) {
-    case AV_OPT_TYPE_PIXEL_FMT:
-        *(enum AVPixelFormat *)dst = llrint(num / den) * intnum;
-        break;
-    case AV_OPT_TYPE_SAMPLE_FMT:
-        *(enum AVSampleFormat *)dst = llrint(num / den) * intnum;
-        break;
-    case AV_OPT_TYPE_BOOL:
-    case AV_OPT_TYPE_FLAGS:
-    case AV_OPT_TYPE_INT:
-        *(int *)dst = llrint(num / den) * intnum;
-        break;
-    case AV_OPT_TYPE_DURATION:
-    case AV_OPT_TYPE_CHANNEL_LAYOUT:
-    case AV_OPT_TYPE_INT64:
-        *(int64_t *)dst = llrint(num / den) * intnum;
-        break;
-    case AV_OPT_TYPE_FLOAT:
-        *(float *)dst = num * intnum / den;
-        break;
-    case AV_OPT_TYPE_DOUBLE:
-        *(double    *)dst = num * intnum / den;
-        break;
-    case AV_OPT_TYPE_RATIONAL:
-    case AV_OPT_TYPE_VIDEO_RATE:
-        if ((int) num == num)
-            *(AVRational *)dst = (AVRational) { num *intnum, den };
-        else
-            *(AVRational *)dst = av_d2q(num * intnum / den, 1 << 24);
-        break;
-    default:
-        return AVERROR(EINVAL);
-    }
-    return 0;
-}
-
-static int hexchar2int(char c) {
-    if (c >= '0' && c <= '9')
-        return c - '0';
-    if (c >= 'a' && c <= 'f')
-        return c - 'a' + 10;
-    if (c >= 'A' && c <= 'F')
-        return c - 'A' + 10;
-    return -1;
-}
-
-static int set_string_binary(void *obj, const AVOption *o, const char *val, uint8_t **dst)
-{
-    int *lendst = (int *)(dst + 1);
-    uint8_t *bin, *ptr;
-    int len;
-
-    av_freep(dst);
-    *lendst = 0;
-
-    if (!val || !(len = strlen(val)))
-        return 0;
-
-    if (len & 1)
-        return AVERROR(EINVAL);
-    len /= 2;
-
-    ptr = bin = av_malloc(len);
-    if (!ptr)
-        return AVERROR(ENOMEM);
-    while (*val) {
-        int a = hexchar2int(*val++);
-        int b = hexchar2int(*val++);
-        if (a < 0 || b < 0) {
-            av_free(bin);
-            return AVERROR(EINVAL);
-        }
-        *ptr++ = (a << 4) | b;
-    }
-    *dst    = bin;
-    *lendst = len;
-
-    return 0;
-}
-
-static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **dst)
-{
-    av_freep(dst);
-    *dst = av_strdup(val);
-    return *dst ? 0 : AVERROR(ENOMEM);
-}
-
-#define DEFAULT_NUMVAL(opt) ((opt->type == AV_OPT_TYPE_INT64 || \
-                              opt->type == AV_OPT_TYPE_CONST || \
-                              opt->type == AV_OPT_TYPE_FLAGS || \
-                              opt->type == AV_OPT_TYPE_INT)     \
-                             ? opt->default_val.i64             \
-                             : opt->default_val.dbl)
-
-static int set_string_number(void *obj, void *target_obj, const AVOption *o, const char *val, void *dst)
-{
-    int ret = 0;
-    int num, den;
-    char c;
-
-    if (sscanf(val, "%d%*1[:/]%d%c", &num, &den, &c) == 2) {
-        if ((ret = write_number(obj, o, dst, 1, den, num)) >= 0)
-            return ret;
-        ret = 0;
-    }
-
-    for (;;) {
-        int i = 0;
-        char buf[256];
-        int cmd = 0;
-        double d;
-        int64_t intnum = 1;
-
-        if (o->type == AV_OPT_TYPE_FLAGS) {
-            if (*val == '+' || *val == '-')
-                cmd = *(val++);
-            for (; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++)
-                buf[i] = val[i];
-            buf[i] = 0;
-        }
-
-        {
-            const AVOption *o_named = av_opt_find(target_obj, i ? buf : val, o->unit, 0, 0);
-            int res;
-            int ci = 0;
-            double const_values[64];
-            const char * const_names[64];
-            if (o_named && o_named->type == AV_OPT_TYPE_CONST)
-                d = DEFAULT_NUMVAL(o_named);
-            else {
-                if (o->unit) {
-                    for (o_named = NULL; o_named = av_opt_next(target_obj, o_named); ) {
-                        if (o_named->type == AV_OPT_TYPE_CONST &&
-                            o_named->unit &&
-                            !strcmp(o_named->unit, o->unit)) {
-                            if (ci + 6 >= FF_ARRAY_ELEMS(const_values)) {
-                                av_log(obj, AV_LOG_ERROR, "const_values array too small for %s\n", o->unit);
-                                return AVERROR_PATCHWELCOME;
-                            }
-                            const_names [ci  ] = o_named->name;
-                            const_values[ci++] = DEFAULT_NUMVAL(o_named);
-                        }
-                    }
-                }
-                const_names [ci  ] = "default";
-                const_values[ci++] = DEFAULT_NUMVAL(o);
-                const_names [ci  ] = "max";
-                const_values[ci++] = o->max;
-                const_names [ci  ] = "min";
-                const_values[ci++] = o->min;
-                const_names [ci  ] = "none";
-                const_values[ci++] = 0;
-                const_names [ci  ] = "all";
-                const_values[ci++] = ~0;
-                const_names [ci] = NULL;
-                const_values[ci] = 0;
-
-                res = av_expr_parse_and_eval(&d, i ? buf : val, const_names,
-                                            const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
-                if (res < 0) {
-                    av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
-                    return res;
-                }
-            }
-        }
-        if (o->type == AV_OPT_TYPE_FLAGS) {
-            read_number(o, dst, NULL, NULL, &intnum);
-            if (cmd == '+')
-                d = intnum | (int64_t)d;
-            else if (cmd == '-')
-                d = intnum &~(int64_t)d;
-        }
-
-        if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0)
-            return ret;
-        val += i;
-        if (!i || !*val)
-            return 0;
-    }
-
-    return 0;
-}
-
-static int set_string_image_size(void *obj, const AVOption *o, const char *val, int *dst)
-{
-    int ret;
-
-    if (!val || !strcmp(val, "none")) {
-        dst[0] =
-        dst[1] = 0;
-        return 0;
-    }
-    ret = av_parse_video_size(dst, dst + 1, val);
-    if (ret < 0)
-        av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as image size\n", val);
-    return ret;
-}
-
-static int set_string_video_rate(void *obj, const AVOption *o, const char *val, AVRational *dst)
-{
-    int ret;
-    if (!val) {
-        ret = AVERROR(EINVAL);
-    } else {
-        ret = av_parse_video_rate(dst, val);
-    }
-    if (ret < 0)
-        av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as video rate\n", val);
-    return ret;
-}
-
-static int set_string_color(void *obj, const AVOption *o, const char *val, uint8_t *dst)
-{
-    int ret;
-
-    if (!val) {
-        return 0;
-    } else {
-        ret = av_parse_color(dst, val, -1, obj);
-        if (ret < 0)
-            av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as color\n", val);
-        return ret;
-    }
-    return 0;
-}
-
-static const char *get_bool_name(int val)
-{
-    if (val < 0)
-        return "auto";
-    return val ? "true" : "false";
-}
-
-static int set_string_bool(void *obj, const AVOption *o, const char *val, int *dst)
-{
-    int n;
-
-    if (!val)
-        return 0;
-
-    if (!strcmp(val, "auto")) {
-        n = -1;
-    } else if (av_match_name(val, "true,y,yes,enable,enabled,on")) {
-        n = 1;
-    } else if (av_match_name(val, "false,n,no,disable,disabled,off")) {
-        n = 0;
-    } else {
-        char *end = NULL;
-        n = strtol(val, &end, 10);
-        if (val + strlen(val) != end)
-            goto fail;
-    }
-
-    if (n < o->min || n > o->max)
-        goto fail;
-
-    *dst = n;
-    return 0;
-
-fail:
-    av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as boolean\n", val);
-    return AVERROR(EINVAL);
-}
-
-static int set_string_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst,
-                          int fmt_nb, int ((*get_fmt)(const char *)), const char *desc)
-{
-    int fmt, min, max;
-
-    if (!val || !strcmp(val, "none")) {
-        fmt = -1;
-    } else {
-        fmt = get_fmt(val);
-        if (fmt == -1) {
-            char *tail;
-            fmt = strtol(val, &tail, 0);
-            if (*tail || (unsigned)fmt >= fmt_nb) {
-                av_log(obj, AV_LOG_ERROR,
-                       "Unable to parse option value \"%s\" as %s\n", val, desc);
-                return AVERROR(EINVAL);
-            }
-        }
-    }
-
-    min = FFMAX(o->min, -1);
-    max = FFMIN(o->max, fmt_nb-1);
-
-    // hack for compatibility with old ffmpeg
-    if(min == 0 && max == 0) {
-        min = -1;
-        max = fmt_nb-1;
-    }
-
-    if (fmt < min || fmt > max) {
-        av_log(obj, AV_LOG_ERROR,
-               "Value %d for parameter '%s' out of %s format range [%d - %d]\n",
-               fmt, o->name, desc, min, max);
-        return AVERROR(ERANGE);
-    }
-
-    *(int *)dst = fmt;
-    return 0;
-}
-
-static int set_string_pixel_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst)
-{
-    return set_string_fmt(obj, o, val, dst,
-                          AV_PIX_FMT_NB, av_get_pix_fmt, "pixel format");
-}
-
-static int set_string_sample_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst)
-{
-    return set_string_fmt(obj, o, val, dst,
-                          AV_SAMPLE_FMT_NB, av_get_sample_fmt, "sample format");
-}
-
-int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
-{
-    int ret = 0;
-    void *dst, *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (!val && (o->type != AV_OPT_TYPE_STRING &&
-                 o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT &&
-                 o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_VIDEO_RATE &&
-                 o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR &&
-                 o->type != AV_OPT_TYPE_CHANNEL_LAYOUT && o->type != AV_OPT_TYPE_BOOL))
-        return AVERROR(EINVAL);
-
-    if (o->flags & AV_OPT_FLAG_READONLY)
-        return AVERROR(EINVAL);
-
-    dst = ((uint8_t *)target_obj) + o->offset;
-    switch (o->type) {
-    case AV_OPT_TYPE_BOOL:
-        return set_string_bool(obj, o, val, dst);
-    case AV_OPT_TYPE_STRING:
-        return set_string(obj, o, val, dst);
-    case AV_OPT_TYPE_BINARY:
-        return set_string_binary(obj, o, val, dst);
-    case AV_OPT_TYPE_FLAGS:
-    case AV_OPT_TYPE_INT:
-    case AV_OPT_TYPE_INT64:
-    case AV_OPT_TYPE_FLOAT:
-    case AV_OPT_TYPE_DOUBLE:
-    case AV_OPT_TYPE_RATIONAL:
-        return set_string_number(obj, target_obj, o, val, dst);
-    case AV_OPT_TYPE_IMAGE_SIZE:
-        return set_string_image_size(obj, o, val, dst);
-    case AV_OPT_TYPE_VIDEO_RATE: {
-        AVRational tmp;
-        ret = set_string_video_rate(obj, o, val, &tmp);
-        if (ret < 0)
-            return ret;
-        return write_number(obj, o, dst, 1, tmp.den, tmp.num);
-    }
-    case AV_OPT_TYPE_PIXEL_FMT:
-        return set_string_pixel_fmt(obj, o, val, dst);
-    case AV_OPT_TYPE_SAMPLE_FMT:
-        return set_string_sample_fmt(obj, o, val, dst);
-    case AV_OPT_TYPE_DURATION:
-        if (!val) {
-            *(int64_t *)dst = 0;
-            return 0;
-        } else {
-            if ((ret = av_parse_time(dst, val, 1)) < 0)
-                av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as duration\n", val);
-            return ret;
-        }
-        break;
-    case AV_OPT_TYPE_COLOR:
-        return set_string_color(obj, o, val, dst);
-    case AV_OPT_TYPE_CHANNEL_LAYOUT:
-        if (!val || !strcmp(val, "none")) {
-            *(int64_t *)dst = 0;
-        } else {
-            int64_t cl = av_get_channel_layout(val);
-            if (!cl) {
-                av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as channel layout\n", val);
-                ret = AVERROR(EINVAL);
-            }
-            *(int64_t *)dst = cl;
-            return ret;
-        }
-        break;
-    }
-
-    av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
-    return AVERROR(EINVAL);
-}
-
-#define OPT_EVAL_NUMBER(name, opttype, vartype)                         \
-int av_opt_eval_ ## name(void *obj, const AVOption *o,                  \
-                         const char *val, vartype *name ## _out)        \
-{                                                                       \
-    if (!o || o->type != opttype || o->flags & AV_OPT_FLAG_READONLY)    \
-        return AVERROR(EINVAL);                                         \
-    return set_string_number(obj, obj, o, val, name ## _out);           \
-}
-
-OPT_EVAL_NUMBER(flags,  AV_OPT_TYPE_FLAGS,    int)
-OPT_EVAL_NUMBER(int,    AV_OPT_TYPE_INT,      int)
-OPT_EVAL_NUMBER(int64,  AV_OPT_TYPE_INT64,    int64_t)
-OPT_EVAL_NUMBER(float,  AV_OPT_TYPE_FLOAT,    float)
-OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE,   double)
-OPT_EVAL_NUMBER(q,      AV_OPT_TYPE_RATIONAL, AVRational)
-
-static int set_number(void *obj, const char *name, double num, int den, int64_t intnum,
-                      int search_flags)
-{
-    void *dst, *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-
-    if (o->flags & AV_OPT_FLAG_READONLY)
-        return AVERROR(EINVAL);
-
-    dst = ((uint8_t *)target_obj) + o->offset;
-    return write_number(obj, o, dst, num, den, intnum);
-}
-
-int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
-{
-    return set_number(obj, name, 1, 1, val, search_flags);
-}
-
-int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
-{
-    return set_number(obj, name, val, 1, 1, search_flags);
-}
-
-int av_opt_set_q(void *obj, const char *name, AVRational val, int search_flags)
-{
-    return set_number(obj, name, val.num, val.den, 1, search_flags);
-}
-
-int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
-{
-    void *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-    uint8_t *ptr;
-    uint8_t **dst;
-    int *lendst;
-
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-
-    if (o->type != AV_OPT_TYPE_BINARY || o->flags & AV_OPT_FLAG_READONLY)
-        return AVERROR(EINVAL);
-
-    ptr = len ? av_malloc(len) : NULL;
-    if (len && !ptr)
-        return AVERROR(ENOMEM);
-
-    dst    = (uint8_t **)(((uint8_t *)target_obj) + o->offset);
-    lendst = (int *)(dst + 1);
-
-    av_free(*dst);
-    *dst    = ptr;
-    *lendst = len;
-    if (len)
-        memcpy(ptr, val, len);
-
-    return 0;
-}
-
-int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags)
-{
-    void *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (o->type != AV_OPT_TYPE_IMAGE_SIZE) {
-        av_log(obj, AV_LOG_ERROR,
-               "The value set by option '%s' is not an image size.\n", o->name);
-        return AVERROR(EINVAL);
-    }
-    if (w<0 || h<0) {
-        av_log(obj, AV_LOG_ERROR,
-               "Invalid negative size value %dx%d for size '%s'\n", w, h, o->name);
-        return AVERROR(EINVAL);
-    }
-    *(int *)(((uint8_t *)target_obj)             + o->offset) = w;
-    *(int *)(((uint8_t *)target_obj+sizeof(int)) + o->offset) = h;
-    return 0;
-}
-
-int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags)
-{
-    void *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (o->type != AV_OPT_TYPE_VIDEO_RATE) {
-        av_log(obj, AV_LOG_ERROR,
-               "The value set by option '%s' is not a video rate.\n", o->name);
-        return AVERROR(EINVAL);
-    }
-    if (val.num <= 0 || val.den <= 0)
-        return AVERROR(EINVAL);
-    return set_number(obj, name, val.num, val.den, 1, search_flags);
-}
-
-static int set_format(void *obj, const char *name, int fmt, int search_flags,
-                      enum AVOptionType type, const char *desc, int nb_fmts)
-{
-    void *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0,
-                                     search_flags, &target_obj);
-    int min, max;
-
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (o->type != type) {
-        av_log(obj, AV_LOG_ERROR,
-               "The value set by option '%s' is not a %s format", name, desc);
-        return AVERROR(EINVAL);
-    }
-
-    min = FFMAX(o->min, -1);
-    max = FFMIN(o->max, nb_fmts-1);
-
-    if (fmt < min || fmt > max) {
-        av_log(obj, AV_LOG_ERROR,
-               "Value %d for parameter '%s' out of %s format range [%d - %d]\n",
-               fmt, name, desc, min, max);
-        return AVERROR(ERANGE);
-    }
-    *(int *)(((uint8_t *)target_obj) + o->offset) = fmt;
-    return 0;
-}
-
-int av_opt_set_pixel_fmt(void *obj, const char *name, enum AVPixelFormat fmt, int search_flags)
-{
-    return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_PIXEL_FMT, "pixel", AV_PIX_FMT_NB);
-}
-
-int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags)
-{
-    return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_SAMPLE_FMT, "sample", AV_SAMPLE_FMT_NB);
-}
-
-int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int search_flags)
-{
-    void *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) {
-        av_log(obj, AV_LOG_ERROR,
-               "The value set by option '%s' is not a channel layout.\n", o->name);
-        return AVERROR(EINVAL);
-    }
-    *(int64_t *)(((uint8_t *)target_obj) + o->offset) = cl;
-    return 0;
-}
-
-int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val,
-                        int search_flags)
-{
-    void *target_obj;
-    AVDictionary **dst;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (o->flags & AV_OPT_FLAG_READONLY)
-        return AVERROR(EINVAL);
-
-    dst = (AVDictionary **)(((uint8_t *)target_obj) + o->offset);
-    av_dict_free(dst);
-    av_dict_copy(dst, val, 0);
-
-    return 0;
-}
-
-static void format_duration(char *buf, size_t size, int64_t d)
-{
-    char *e;
-
-    av_assert0(size >= 25);
-    if (d < 0 && d != INT64_MIN) {
-        *(buf++) = '-';
-        size--;
-        d = -d;
-    }
-    if (d == INT64_MAX)
-        snprintf(buf, size, "INT64_MAX");
-    else if (d == INT64_MIN)
-        snprintf(buf, size, "INT64_MIN");
-    else if (d > (int64_t)3600*1000000)
-        snprintf(buf, size, "%"PRId64":%02d:%02d.%06d", d / 3600000000,
-                 (int)((d / 60000000) % 60),
-                 (int)((d / 1000000) % 60),
-                 (int)(d % 1000000));
-    else if (d > 60*1000000)
-        snprintf(buf, size, "%d:%02d.%06d",
-                 (int)(d / 60000000),
-                 (int)((d / 1000000) % 60),
-                 (int)(d % 1000000));
-    else
-        snprintf(buf, size, "%d.%06d",
-                 (int)(d / 1000000),
-                 (int)(d % 1000000));
-    e = buf + strlen(buf);
-    while (e > buf && e[-1] == '0')
-        *(--e) = 0;
-    if (e > buf && e[-1] == '.')
-        *(--e) = 0;
-}
-
-int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
-{
-    void *dst, *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-    uint8_t *bin, buf[128];
-    int len, i, ret;
-    int64_t i64;
-
-    if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST))
-        return AVERROR_OPTION_NOT_FOUND;
-
-    dst = (uint8_t *)target_obj + o->offset;
-
-    buf[0] = 0;
-    switch (o->type) {
-    case AV_OPT_TYPE_BOOL:
-        ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(get_bool_name(*(int *)dst), "invalid"));
-        break;
-    case AV_OPT_TYPE_FLAGS:
-        ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst);
-        break;
-    case AV_OPT_TYPE_INT:
-        ret = snprintf(buf, sizeof(buf), "%d", *(int *)dst);
-        break;
-    case AV_OPT_TYPE_INT64:
-        ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t *)dst);
-        break;
-    case AV_OPT_TYPE_FLOAT:
-        ret = snprintf(buf, sizeof(buf), "%f", *(float *)dst);
-        break;
-    case AV_OPT_TYPE_DOUBLE:
-        ret = snprintf(buf, sizeof(buf), "%f", *(double *)dst);
-        break;
-    case AV_OPT_TYPE_VIDEO_RATE:
-    case AV_OPT_TYPE_RATIONAL:
-        ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational *)dst)->num, ((AVRational *)dst)->den);
-        break;
-    case AV_OPT_TYPE_CONST:
-        ret = snprintf(buf, sizeof(buf), "%f", o->default_val.dbl);
-        break;
-    case AV_OPT_TYPE_STRING:
-        if (*(uint8_t **)dst) {
-            *out_val = av_strdup(*(uint8_t **)dst);
-        } else if (search_flags & AV_OPT_ALLOW_NULL) {
-            *out_val = NULL;
-            return 0;
-        } else {
-            *out_val = av_strdup("");
-        }
-        return *out_val ? 0 : AVERROR(ENOMEM);
-    case AV_OPT_TYPE_BINARY:
-        if (!*(uint8_t **)dst && (search_flags & AV_OPT_ALLOW_NULL)) {
-            *out_val = NULL;
-            return 0;
-        }
-        len = *(int *)(((uint8_t *)dst) + sizeof(uint8_t *));
-        if ((uint64_t)len * 2 + 1 > INT_MAX)
-            return AVERROR(EINVAL);
-        if (!(*out_val = av_malloc(len * 2 + 1)))
-            return AVERROR(ENOMEM);
-        if (!len) {
-            *out_val[0] = '\0';
-            return 0;
-        }
-        bin = *(uint8_t **)dst;
-        for (i = 0; i < len; i++)
-            snprintf(*out_val + i * 2, 3, "%02X", bin[i]);
-        return 0;
-    case AV_OPT_TYPE_IMAGE_SIZE:
-        ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]);
-        break;
-    case AV_OPT_TYPE_PIXEL_FMT:
-        ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_pix_fmt_name(*(enum AVPixelFormat *)dst), "none"));
-        break;
-    case AV_OPT_TYPE_SAMPLE_FMT:
-        ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_sample_fmt_name(*(enum AVSampleFormat *)dst), "none"));
-        break;
-    case AV_OPT_TYPE_DURATION:
-        i64 = *(int64_t *)dst;
-        format_duration(buf, sizeof(buf), i64);
-        ret = strlen(buf); // no overflow possible, checked by an assert
-        break;
-    case AV_OPT_TYPE_COLOR:
-        ret = snprintf(buf, sizeof(buf), "0x%02x%02x%02x%02x",
-                       (int)((uint8_t *)dst)[0], (int)((uint8_t *)dst)[1],
-                       (int)((uint8_t *)dst)[2], (int)((uint8_t *)dst)[3]);
-        break;
-    case AV_OPT_TYPE_CHANNEL_LAYOUT:
-        i64 = *(int64_t *)dst;
-        ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64);
-        break;
-    default:
-        return AVERROR(EINVAL);
-    }
-
-    if (ret >= sizeof(buf))
-        return AVERROR(EINVAL);
-    *out_val = av_strdup(buf);
-    return *out_val ? 0 : AVERROR(ENOMEM);
-}
-
-static int get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum,
-                      int search_flags)
-{
-    void *dst, *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-    if (!o || !target_obj)
-        goto error;
-
-    dst = ((uint8_t *)target_obj) + o->offset;
-
-    if (o_out) *o_out= o;
-
-    return read_number(o, dst, num, den, intnum);
-
-error:
-    *den    =
-    *intnum = 0;
-    return -1;
-}
-
-int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val)
-{
-    int64_t intnum = 1;
-    double num = 1;
-    int ret, den = 1;
-
-    if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
-        return ret;
-    *out_val = num * intnum / den;
-    return 0;
-}
-
-int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val)
-{
-    int64_t intnum = 1;
-    double num = 1;
-    int ret, den = 1;
-
-    if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
-        return ret;
-    *out_val = num * intnum / den;
-    return 0;
-}
-
-int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val)
-{
-    int64_t intnum = 1;
-    double num = 1;
-    int ret, den = 1;
-
-    if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
-        return ret;
-
-    if (num == 1.0 && (int)intnum == intnum)
-        *out_val = (AVRational){intnum, den};
-    else
-        *out_val = av_d2q(num*intnum/den, 1<<24);
-    return 0;
-}
-
-int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out)
-{
-    void *dst, *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (o->type != AV_OPT_TYPE_IMAGE_SIZE) {
-        av_log(obj, AV_LOG_ERROR,
-               "The value for option '%s' is not an image size.\n", name);
-        return AVERROR(EINVAL);
-    }
-
-    dst = ((uint8_t*)target_obj) + o->offset;
-    if (w_out) *w_out = *(int *)dst;
-    if (h_out) *h_out = *((int *)dst+1);
-    return 0;
-}
-
-int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val)
-{
-    int64_t intnum = 1;
-    double     num = 1;
-    int   ret, den = 1;
-
-    if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
-        return ret;
-
-    if (num == 1.0 && (int)intnum == intnum)
-        *out_val = (AVRational) { intnum, den };
-    else
-        *out_val = av_d2q(num * intnum / den, 1 << 24);
-    return 0;
-}
-
-static int get_format(void *obj, const char *name, int search_flags, int *out_fmt,
-                      enum AVOptionType type, const char *desc)
-{
-    void *dst, *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (o->type != type) {
-        av_log(obj, AV_LOG_ERROR,
-               "The value for option '%s' is not a %s format.\n", desc, name);
-        return AVERROR(EINVAL);
-    }
-
-    dst = ((uint8_t*)target_obj) + o->offset;
-    *out_fmt = *(int *)dst;
-    return 0;
-}
-
-int av_opt_get_pixel_fmt(void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt)
-{
-    return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_PIXEL_FMT, "pixel");
-}
-
-int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt)
-{
-    return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_SAMPLE_FMT, "sample");
-}
-
-int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *cl)
-{
-    void *dst, *target_obj;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) {
-        av_log(obj, AV_LOG_ERROR,
-               "The value for option '%s' is not a channel layout.\n", name);
-        return AVERROR(EINVAL);
-    }
-
-    dst = ((uint8_t*)target_obj) + o->offset;
-    *cl = *(int64_t *)dst;
-    return 0;
-}
-
-int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val)
-{
-    void *target_obj;
-    AVDictionary *src;
-    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
-
-    if (!o || !target_obj)
-        return AVERROR_OPTION_NOT_FOUND;
-    if (o->type != AV_OPT_TYPE_DICT)
-        return AVERROR(EINVAL);
-
-    src = *(AVDictionary **)(((uint8_t *)target_obj) + o->offset);
-    av_dict_copy(out_val, src, 0);
-
-    return 0;
-}
-
-int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
-{
-    const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
-    const AVOption *flag  = av_opt_find(obj, flag_name,
-                                        field ? field->unit : NULL, 0, 0);
-    int64_t res;
-
-    if (!field || !flag || flag->type != AV_OPT_TYPE_CONST ||
-        av_opt_get_int(obj, field_name, 0, &res) < 0)
-        return 0;
-    return res & flag->default_val.i64;
-}
-
-static void log_value(void *av_log_obj, int level, double d)
-{
-    if      (d == INT_MAX) {
-        av_log(av_log_obj, level, "INT_MAX");
-    } else if (d == INT_MIN) {
-        av_log(av_log_obj, level, "INT_MIN");
-    } else if (d == UINT32_MAX) {
-        av_log(av_log_obj, level, "UINT32_MAX");
-    } else if (d == (double)INT64_MAX) {
-        av_log(av_log_obj, level, "I64_MAX");
-    } else if (d == INT64_MIN) {
-        av_log(av_log_obj, level, "I64_MIN");
-    } else if (d == FLT_MAX) {
-        av_log(av_log_obj, level, "FLT_MAX");
-    } else if (d == FLT_MIN) {
-        av_log(av_log_obj, level, "FLT_MIN");
-    } else if (d == -FLT_MAX) {
-        av_log(av_log_obj, level, "-FLT_MAX");
-    } else if (d == -FLT_MIN) {
-        av_log(av_log_obj, level, "-FLT_MIN");
-    } else if (d == DBL_MAX) {
-        av_log(av_log_obj, level, "DBL_MAX");
-    } else if (d == DBL_MIN) {
-        av_log(av_log_obj, level, "DBL_MIN");
-    } else if (d == -DBL_MAX) {
-        av_log(av_log_obj, level, "-DBL_MAX");
-    } else if (d == -DBL_MIN) {
-        av_log(av_log_obj, level, "-DBL_MIN");
-    } else {
-        av_log(av_log_obj, level, "%g", d);
-    }
-}
-
-static const char *get_opt_const_name(void *obj, const char *unit, int64_t value)
-{
-    const AVOption *opt = NULL;
-
-    if (!unit)
-        return NULL;
-    while ((opt = av_opt_next(obj, opt)))
-        if (opt->type == AV_OPT_TYPE_CONST && !strcmp(opt->unit, unit) &&
-            opt->default_val.i64 == value)
-            return opt->name;
-    return NULL;
-}
-
-static char *get_opt_flags_string(void *obj, const char *unit, int64_t value)
-{
-    const AVOption *opt = NULL;
-    char flags[512];
-
-    flags[0] = 0;
-    if (!unit)
-        return NULL;
-    while ((opt = av_opt_next(obj, opt))) {
-        if (opt->type == AV_OPT_TYPE_CONST && !strcmp(opt->unit, unit) &&
-            opt->default_val.i64 & value) {
-            if (flags[0])
-                av_strlcatf(flags, sizeof(flags), "+");
-            av_strlcatf(flags, sizeof(flags), "%s", opt->name);
-        }
-    }
-    if (flags[0])
-        return av_strdup(flags);
-    return NULL;
-}
-
-static void opt_list(void *obj, void *av_log_obj, const char *unit,
-                     int req_flags, int rej_flags)
-{
-    const AVOption *opt = NULL;
-    AVOptionRanges *r;
-    int i;
-
-    while ((opt = av_opt_next(obj, opt))) {
-        if (!(opt->flags & req_flags) || (opt->flags & rej_flags))
-            continue;
-
-        /* Don't print CONST's on level one.
-         * Don't print anything but CONST's on level two.
-         * Only print items from the requested unit.
-         */
-        if (!unit && opt->type == AV_OPT_TYPE_CONST)
-            continue;
-        else if (unit && opt->type != AV_OPT_TYPE_CONST)
-            continue;
-        else if (unit && opt->type == AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
-            continue;
-        else if (unit && opt->type == AV_OPT_TYPE_CONST)
-            av_log(av_log_obj, AV_LOG_INFO, "     %-15s ", opt->name);
-        else
-            av_log(av_log_obj, AV_LOG_INFO, "  %s%-17s ",
-                   (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? "" : "-",
-                   opt->name);
-
-        switch (opt->type) {
-            case AV_OPT_TYPE_FLAGS:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<flags>");
-                break;
-            case AV_OPT_TYPE_INT:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int>");
-                break;
-            case AV_OPT_TYPE_INT64:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int64>");
-                break;
-            case AV_OPT_TYPE_DOUBLE:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<double>");
-                break;
-            case AV_OPT_TYPE_FLOAT:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<float>");
-                break;
-            case AV_OPT_TYPE_STRING:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<string>");
-                break;
-            case AV_OPT_TYPE_RATIONAL:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<rational>");
-                break;
-            case AV_OPT_TYPE_BINARY:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<binary>");
-                break;
-            case AV_OPT_TYPE_IMAGE_SIZE:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<image_size>");
-                break;
-            case AV_OPT_TYPE_VIDEO_RATE:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<video_rate>");
-                break;
-            case AV_OPT_TYPE_PIXEL_FMT:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<pix_fmt>");
-                break;
-            case AV_OPT_TYPE_SAMPLE_FMT:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<sample_fmt>");
-                break;
-            case AV_OPT_TYPE_DURATION:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<duration>");
-                break;
-            case AV_OPT_TYPE_COLOR:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<color>");
-                break;
-            case AV_OPT_TYPE_CHANNEL_LAYOUT:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<channel_layout>");
-                break;
-            case AV_OPT_TYPE_BOOL:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<boolean>");
-                break;
-            case AV_OPT_TYPE_CONST:
-            default:
-                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "");
-                break;
-        }
-        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
-        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
-        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_FILTERING_PARAM)? 'F' : '.');
-        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM   ) ? 'V' : '.');
-        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM   ) ? 'A' : '.');
-        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
-        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_EXPORT)         ? 'X' : '.');
-        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_READONLY)       ? 'R' : '.');
-
-        if (opt->help)
-            av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
-
-        if (av_opt_query_ranges(&r, obj, opt->name, AV_OPT_SEARCH_FAKE_OBJ) >= 0) {
-            switch (opt->type) {
-            case AV_OPT_TYPE_INT:
-            case AV_OPT_TYPE_INT64:
-            case AV_OPT_TYPE_DOUBLE:
-            case AV_OPT_TYPE_FLOAT:
-            case AV_OPT_TYPE_RATIONAL:
-                for (i = 0; i < r->nb_ranges; i++) {
-                    av_log(av_log_obj, AV_LOG_INFO, " (from ");
-                    log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_min);
-                    av_log(av_log_obj, AV_LOG_INFO, " to ");
-                    log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_max);
-                    av_log(av_log_obj, AV_LOG_INFO, ")");
-                }
-                break;
-            }
-            av_opt_freep_ranges(&r);
-        }
-
-        if (opt->type != AV_OPT_TYPE_CONST  &&
-            opt->type != AV_OPT_TYPE_BINARY &&
-                !((opt->type == AV_OPT_TYPE_COLOR      ||
-                   opt->type == AV_OPT_TYPE_IMAGE_SIZE ||
-                   opt->type == AV_OPT_TYPE_STRING     ||
-                   opt->type == AV_OPT_TYPE_VIDEO_RATE) &&
-                  !opt->default_val.str)) {
-            av_log(av_log_obj, AV_LOG_INFO, " (default ");
-            switch (opt->type) {
-            case AV_OPT_TYPE_BOOL:
-                av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(get_bool_name(opt->default_val.i64), "invalid"));
-                break;
-            case AV_OPT_TYPE_FLAGS: {
-                char *def_flags = get_opt_flags_string(obj, opt->unit, opt->default_val.i64);
-                if (def_flags) {
-                    av_log(av_log_obj, AV_LOG_INFO, "%s", def_flags);
-                    av_freep(&def_flags);
-                } else {
-                    av_log(av_log_obj, AV_LOG_INFO, "%"PRIX64, opt->default_val.i64);
-                }
-                break;
-            }
-            case AV_OPT_TYPE_DURATION: {
-                char buf[25];
-                format_duration(buf, sizeof(buf), opt->default_val.i64);
-                av_log(av_log_obj, AV_LOG_INFO, "%s", buf);
-                break;
-            }
-            case AV_OPT_TYPE_INT:
-            case AV_OPT_TYPE_INT64: {
-                const char *def_const = get_opt_const_name(obj, opt->unit, opt->default_val.i64);
-                if (def_const)
-                    av_log(av_log_obj, AV_LOG_INFO, "%s", def_const);
-                else
-                    log_value(av_log_obj, AV_LOG_INFO, opt->default_val.i64);
-                break;
-            }
-            case AV_OPT_TYPE_DOUBLE:
-            case AV_OPT_TYPE_FLOAT:
-                log_value(av_log_obj, AV_LOG_INFO, opt->default_val.dbl);
-                break;
-            case AV_OPT_TYPE_RATIONAL: {
-                AVRational q = av_d2q(opt->default_val.dbl, INT_MAX);
-                av_log(av_log_obj, AV_LOG_INFO, "%d/%d", q.num, q.den); }
-                break;
-            case AV_OPT_TYPE_PIXEL_FMT:
-                av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_pix_fmt_name(opt->default_val.i64), "none"));
-                break;
-            case AV_OPT_TYPE_SAMPLE_FMT:
-                av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_sample_fmt_name(opt->default_val.i64), "none"));
-                break;
-            case AV_OPT_TYPE_COLOR:
-            case AV_OPT_TYPE_IMAGE_SIZE:
-            case AV_OPT_TYPE_STRING:
-            case AV_OPT_TYPE_VIDEO_RATE:
-                av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str);
-                break;
-            case AV_OPT_TYPE_CHANNEL_LAYOUT:
-                av_log(av_log_obj, AV_LOG_INFO, "0x%"PRIx64, opt->default_val.i64);
-                break;
-            }
-            av_log(av_log_obj, AV_LOG_INFO, ")");
-        }
-
-        av_log(av_log_obj, AV_LOG_INFO, "\n");
-        if (opt->unit && opt->type != AV_OPT_TYPE_CONST)
-            opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
-    }
-}
-
-int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
-{
-    if (!obj)
-        return -1;
-
-    av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass **)obj)->class_name);
-
-    opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);
-
-    return 0;
-}
-
-void av_opt_set_defaults(void *s)
-{
-    av_opt_set_defaults2(s, 0, 0);
-}
-
-void av_opt_set_defaults2(void *s, int mask, int flags)
-{
-    const AVOption *opt = NULL;
-    while ((opt = av_opt_next(s, opt))) {
-        void *dst = ((uint8_t*)s) + opt->offset;
-
-        if ((opt->flags & mask) != flags)
-            continue;
-
-        if (opt->flags & AV_OPT_FLAG_READONLY)
-            continue;
-
-        switch (opt->type) {
-            case AV_OPT_TYPE_CONST:
-                /* Nothing to be done here */
-                break;
-            case AV_OPT_TYPE_BOOL:
-            case AV_OPT_TYPE_FLAGS:
-            case AV_OPT_TYPE_INT:
-            case AV_OPT_TYPE_INT64:
-            case AV_OPT_TYPE_DURATION:
-            case AV_OPT_TYPE_CHANNEL_LAYOUT:
-            case AV_OPT_TYPE_PIXEL_FMT:
-            case AV_OPT_TYPE_SAMPLE_FMT:
-                write_number(s, opt, dst, 1, 1, opt->default_val.i64);
-                break;
-            case AV_OPT_TYPE_DOUBLE:
-            case AV_OPT_TYPE_FLOAT: {
-                double val;
-                val = opt->default_val.dbl;
-                write_number(s, opt, dst, val, 1, 1);
-            }
-            break;
-            case AV_OPT_TYPE_RATIONAL: {
-                AVRational val;
-                val = av_d2q(opt->default_val.dbl, INT_MAX);
-                write_number(s, opt, dst, 1, val.den, val.num);
-            }
-            break;
-            case AV_OPT_TYPE_COLOR:
-                set_string_color(s, opt, opt->default_val.str, dst);
-                break;
-            case AV_OPT_TYPE_STRING:
-                set_string(s, opt, opt->default_val.str, dst);
-                break;
-            case AV_OPT_TYPE_IMAGE_SIZE:
-                set_string_image_size(s, opt, opt->default_val.str, dst);
-                break;
-            case AV_OPT_TYPE_VIDEO_RATE:
-                set_string_video_rate(s, opt, opt->default_val.str, dst);
-                break;
-            case AV_OPT_TYPE_BINARY:
-                set_string_binary(s, opt, opt->default_val.str, dst);
-                break;
-            case AV_OPT_TYPE_DICT:
-                /* Cannot set defaults for these types */
-            break;
-        default:
-            av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n",
-                   opt->type, opt->name);
-        }
-    }
-}
-
-/**
- * Store the value in the field in ctx that is named like key.
- * ctx must be an AVClass context, storing is done using AVOptions.
- *
- * @param buf the string to parse, buf will be updated to point at the
- * separator just after the parsed key/value pair
- * @param key_val_sep a 0-terminated list of characters used to
- * separate key from value
- * @param pairs_sep a 0-terminated list of characters used to separate
- * two pairs from each other
- * @return 0 if the key/value pair has been successfully parsed and
- * set, or a negative value corresponding to an AVERROR code in case
- * of error:
- * AVERROR(EINVAL) if the key/value pair cannot be parsed,
- * the error code issued by av_opt_set() if the key/value pair
- * cannot be set
- */
-static int parse_key_value_pair(void *ctx, const char **buf,
-                                const char *key_val_sep, const char *pairs_sep)
-{
-    char *key = av_get_token(buf, key_val_sep);
-    char *val;
-    int ret;
-
-    if (!key)
-        return AVERROR(ENOMEM);
-
-    if (*key && strspn(*buf, key_val_sep)) {
-        (*buf)++;
-        val = av_get_token(buf, pairs_sep);
-        if (!val) {
-            av_freep(&key);
-            return AVERROR(ENOMEM);
-        }
-    } else {
-        av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
-        av_free(key);
-        return AVERROR(EINVAL);
-    }
-
-    av_log(ctx, AV_LOG_DEBUG, "Setting entry with key '%s' to value '%s'\n", key, val);
-
-    ret = av_opt_set(ctx, key, val, AV_OPT_SEARCH_CHILDREN);
-    if (ret == AVERROR_OPTION_NOT_FOUND)
-        av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
-
-    av_free(key);
-    av_free(val);
-    return ret;
-}
-
-int av_set_options_string(void *ctx, const char *opts,
-                          const char *key_val_sep, const char *pairs_sep)
-{
-    int ret, count = 0;
-
-    if (!opts)
-        return 0;
-
-    while (*opts) {
-        if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
-            return ret;
-        count++;
-
-        if (*opts)
-            opts++;
-    }
-
-    return count;
-}
-
-#define WHITESPACES " \n\t\r"
-
-static int is_key_char(char c)
-{
-    return (unsigned)((c | 32) - 'a') < 26 ||
-           (unsigned)(c - '0') < 10 ||
-           c == '-' || c == '_' || c == '/' || c == '.';
-}
-
-/**
- * Read a key from a string.
- *
- * The key consists of is_key_char characters and must be terminated by a
- * character from the delim string; spaces are ignored.
- *
- * @return  0 for success (even with ellipsis), <0 for failure
- */
-static int get_key(const char **ropts, const char *delim, char **rkey)
-{
-    const char *opts = *ropts;
-    const char *key_start, *key_end;
-
-    key_start = opts += strspn(opts, WHITESPACES);
-    while (is_key_char(*opts))
-        opts++;
-    key_end = opts;
-    opts += strspn(opts, WHITESPACES);
-    if (!*opts || !strchr(delim, *opts))
-        return AVERROR(EINVAL);
-    opts++;
-    if (!(*rkey = av_malloc(key_end - key_start + 1)))
-        return AVERROR(ENOMEM);
-    memcpy(*rkey, key_start, key_end - key_start);
-    (*rkey)[key_end - key_start] = 0;
-    *ropts = opts;
-    return 0;
-}
-
-int av_opt_get_key_value(const char **ropts,
-                         const char *key_val_sep, const char *pairs_sep,
-                         unsigned flags,
-                         char **rkey, char **rval)
-{
-    int ret;
-    char *key = NULL, *val;
-    const char *opts = *ropts;
-
-    if ((ret = get_key(&opts, key_val_sep, &key)) < 0 &&
-        !(flags & AV_OPT_FLAG_IMPLICIT_KEY))
-        return AVERROR(EINVAL);
-    if (!(val = av_get_token(&opts, pairs_sep))) {
-        av_free(key);
-        return AVERROR(ENOMEM);
-    }
-    *ropts = opts;
-    *rkey  = key;
-    *rval  = val;
-    return 0;
-}
-
-int av_opt_set_from_string(void *ctx, const char *opts,
-                           const char *const *shorthand,
-                           const char *key_val_sep, const char *pairs_sep)
-{
-    int ret, count = 0;
-    const char *dummy_shorthand = NULL;
-    char *av_uninit(parsed_key), *av_uninit(value);
-    const char *key;
-
-    if (!opts)
-        return 0;
-    if (!shorthand)
-        shorthand = &dummy_shorthand;
-
-    while (*opts) {
-        ret = av_opt_get_key_value(&opts, key_val_sep, pairs_sep,
-                                   *shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0,
-                                   &parsed_key, &value);
-        if (ret < 0) {
-            if (ret == AVERROR(EINVAL))
-                av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", opts);
-            else
-                av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", opts,
-                       av_err2str(ret));
-            return ret;
-        }
-        if (*opts)
-            opts++;
-        if (parsed_key) {
-            key = parsed_key;
-            while (*shorthand) /* discard all remaining shorthand */
-                shorthand++;
-        } else {
-            key = *(shorthand++);
-        }
-
-        av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value);
-        if ((ret = av_opt_set(ctx, key, value, 0)) < 0) {
-            if (ret == AVERROR_OPTION_NOT_FOUND)
-                av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key);
-            av_free(value);
-            av_free(parsed_key);
-            return ret;
-        }
-
-        av_free(value);
-        av_free(parsed_key);
-        count++;
-    }
-    return count;
-}
-
-void av_opt_free(void *obj)
-{
-    const AVOption *o = NULL;
-    while ((o = av_opt_next(obj, o))) {
-        switch (o->type) {
-        case AV_OPT_TYPE_STRING:
-        case AV_OPT_TYPE_BINARY:
-            av_freep((uint8_t *)obj + o->offset);
-            break;
-
-        case AV_OPT_TYPE_DICT:
-            av_dict_free((AVDictionary **)(((uint8_t *)obj) + o->offset));
-            break;
-
-        default:
-            break;
-        }
-    }
-}
-
-int av_opt_set_dict2(void *obj, AVDictionary **options, int search_flags)
-{
-    AVDictionaryEntry *t = NULL;
-    AVDictionary    *tmp = NULL;
-    int ret = 0;
-
-    if (!options)
-        return 0;
-
-    while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) {
-        ret = av_opt_set(obj, t->key, t->value, search_flags);
-        if (ret == AVERROR_OPTION_NOT_FOUND)
-            ret = av_dict_set(&tmp, t->key, t->value, 0);
-        if (ret < 0) {
-            av_log(obj, AV_LOG_ERROR, "Error setting option %s to value %s.\n", t->key, t->value);
-            av_dict_free(&tmp);
-            return ret;
-        }
-        ret = 0;
-    }
-    av_dict_free(options);
-    *options = tmp;
-    return ret;
-}
-
-int av_opt_set_dict(void *obj, AVDictionary **options)
-{
-    return av_opt_set_dict2(obj, options, 0);
-}
-
-const AVOption *av_opt_find(void *obj, const char *name, const char *unit,
-                            int opt_flags, int search_flags)
-{
-    return av_opt_find2(obj, name, unit, opt_flags, search_flags, NULL);
-}
-
-const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
-                             int opt_flags, int search_flags, void **target_obj)
-{
-    const AVClass  *c;
-    const AVOption *o = NULL;
-
-    if(!obj)
-        return NULL;
-
-    c= *(AVClass**)obj;
-
-    if (!c)
-        return NULL;
-
-    if (search_flags & AV_OPT_SEARCH_CHILDREN) {
-        if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
-            const AVClass *child = NULL;
-            while (child = av_opt_child_class_next(c, child))
-                if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL))
-                    return o;
-        } else {
-            void *child = NULL;
-            while (child = av_opt_child_next(obj, child))
-                if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj))
-                    return o;
-        }
-    }
-
-    while (o = av_opt_next(obj, o)) {
-        if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags &&
-            ((!unit && o->type != AV_OPT_TYPE_CONST) ||
-             (unit  && o->type == AV_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)))) {
-            if (target_obj) {
-                if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
-                    *target_obj = obj;
-                else
-                    *target_obj = NULL;
-            }
-            return o;
-        }
-    }
-    return NULL;
-}
-
-void *av_opt_child_next(void *obj, void *prev)
-{
-    const AVClass *c = *(AVClass **)obj;
-    if (c->child_next)
-        return c->child_next(obj, prev);
-    return NULL;
-}
-
-const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev)
-{
-    if (parent->child_class_next)
-        return parent->child_class_next(prev);
-    return NULL;
-}
-
-void *av_opt_ptr(const AVClass *class, void *obj, const char *name)
-{
-    const AVOption *opt= av_opt_find2(&class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL);
-    if(!opt)
-        return NULL;
-    return (uint8_t*)obj + opt->offset;
-}
-
-static int opt_size(enum AVOptionType type)
-{
-    switch(type) {
-    case AV_OPT_TYPE_BOOL:
-    case AV_OPT_TYPE_INT:
-    case AV_OPT_TYPE_FLAGS:
-        return sizeof(int);
-    case AV_OPT_TYPE_DURATION:
-    case AV_OPT_TYPE_CHANNEL_LAYOUT:
-    case AV_OPT_TYPE_INT64:
-        return sizeof(int64_t);
-    case AV_OPT_TYPE_DOUBLE:
-        return sizeof(double);
-    case AV_OPT_TYPE_FLOAT:
-        return sizeof(float);
-    case AV_OPT_TYPE_STRING:
-        return sizeof(uint8_t*);
-    case AV_OPT_TYPE_VIDEO_RATE:
-    case AV_OPT_TYPE_RATIONAL:
-        return sizeof(AVRational);
-    case AV_OPT_TYPE_BINARY:
-        return sizeof(uint8_t*) + sizeof(int);
-    case AV_OPT_TYPE_IMAGE_SIZE:
-        return sizeof(int[2]);
-    case AV_OPT_TYPE_PIXEL_FMT:
-        return sizeof(enum AVPixelFormat);
-    case AV_OPT_TYPE_SAMPLE_FMT:
-        return sizeof(enum AVSampleFormat);
-    case AV_OPT_TYPE_COLOR:
-        return 4;
-    }
-    return AVERROR(EINVAL);
-}
-
-int av_opt_copy(void *dst, const void *src)
-{
-    const AVOption *o = NULL;
-    const AVClass *c;
-    int ret = 0;
-
-    if (!src)
-        return AVERROR(EINVAL);
-
-    c = *(AVClass **)src;
-    if (!c || c != *(AVClass **)dst)
-        return AVERROR(EINVAL);
-
-    while ((o = av_opt_next(src, o))) {
-        void *field_dst = (uint8_t *)dst + o->offset;
-        void *field_src = (uint8_t *)src + o->offset;
-        uint8_t **field_dst8 = (uint8_t **)field_dst;
-        uint8_t **field_src8 = (uint8_t **)field_src;
-
-        if (o->type == AV_OPT_TYPE_STRING) {
-            if (*field_dst8 != *field_src8)
-                av_freep(field_dst8);
-            *field_dst8 = av_strdup(*field_src8);
-            if (*field_src8 && !*field_dst8)
-                ret = AVERROR(ENOMEM);
-        } else if (o->type == AV_OPT_TYPE_BINARY) {
-            int len = *(int *)(field_src8 + 1);
-            if (*field_dst8 != *field_src8)
-                av_freep(field_dst8);
-            *field_dst8 = av_memdup(*field_src8, len);
-            if (len && !*field_dst8) {
-                ret = AVERROR(ENOMEM);
-                len = 0;
-            }
-            *(int *)(field_dst8 + 1) = len;
-        } else if (o->type == AV_OPT_TYPE_CONST) {
-            // do nothing
-        } else if (o->type == AV_OPT_TYPE_DICT) {
-            AVDictionary **sdict = (AVDictionary **) field_src;
-            AVDictionary **ddict = (AVDictionary **) field_dst;
-            if (*sdict != *ddict)
-                av_dict_free(ddict);
-            *ddict = NULL;
-            av_dict_copy(ddict, *sdict, 0);
-            if (av_dict_count(*sdict) != av_dict_count(*ddict))
-                ret = AVERROR(ENOMEM);
-        } else {
-            int size = opt_size(o->type);
-            if (size < 0)
-                ret = size;
-            else
-                memcpy(field_dst, field_src, size);
-        }
-    }
-    return ret;
-}
-
-int av_opt_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags)
-{
-    int ret;
-    const AVClass *c = *(AVClass**)obj;
-    int (*callback)(AVOptionRanges **, void *obj, const char *key, int flags) = NULL;
-
-    if (c->version > (52 << 16 | 11 << 8))
-        callback = c->query_ranges;
-
-    if (!callback)
-        callback = av_opt_query_ranges_default;
-
-    ret = callback(ranges_arg, obj, key, flags);
-    if (ret >= 0) {
-        if (!(flags & AV_OPT_MULTI_COMPONENT_RANGE))
-            ret = 1;
-        (*ranges_arg)->nb_components = ret;
-    }
-    return ret;
-}
-
-int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags)
-{
-    AVOptionRanges *ranges = av_mallocz(sizeof(*ranges));
-    AVOptionRange **range_array = av_mallocz(sizeof(void*));
-    AVOptionRange *range = av_mallocz(sizeof(*range));
-    const AVOption *field = av_opt_find(obj, key, NULL, 0, flags);
-    int ret;
-
-    *ranges_arg = NULL;
-
-    if (!ranges || !range || !range_array || !field) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    ranges->range = range_array;
-    ranges->range[0] = range;
-    ranges->nb_ranges = 1;
-    ranges->nb_components = 1;
-    range->is_range = 1;
-    range->value_min = field->min;
-    range->value_max = field->max;
-
-    switch (field->type) {
-    case AV_OPT_TYPE_BOOL:
-    case AV_OPT_TYPE_INT:
-    case AV_OPT_TYPE_INT64:
-    case AV_OPT_TYPE_PIXEL_FMT:
-    case AV_OPT_TYPE_SAMPLE_FMT:
-    case AV_OPT_TYPE_FLOAT:
-    case AV_OPT_TYPE_DOUBLE:
-    case AV_OPT_TYPE_DURATION:
-    case AV_OPT_TYPE_COLOR:
-    case AV_OPT_TYPE_CHANNEL_LAYOUT:
-        break;
-    case AV_OPT_TYPE_STRING:
-        range->component_min = 0;
-        range->component_max = 0x10FFFF; // max unicode value
-        range->value_min = -1;
-        range->value_max = INT_MAX;
-        break;
-    case AV_OPT_TYPE_RATIONAL:
-        range->component_min = INT_MIN;
-        range->component_max = INT_MAX;
-        break;
-    case AV_OPT_TYPE_IMAGE_SIZE:
-        range->component_min = 0;
-        range->component_max = INT_MAX/128/8;
-        range->value_min = 0;
-        range->value_max = INT_MAX/8;
-        break;
-    case AV_OPT_TYPE_VIDEO_RATE:
-        range->component_min = 1;
-        range->component_max = INT_MAX;
-        range->value_min = 1;
-        range->value_max = INT_MAX;
-        break;
-    default:
-        ret = AVERROR(ENOSYS);
-        goto fail;
-    }
-
-    *ranges_arg = ranges;
-    return 1;
-fail:
-    av_free(ranges);
-    av_free(range);
-    av_free(range_array);
-    return ret;
-}
-
-void av_opt_freep_ranges(AVOptionRanges **rangesp)
-{
-    int i;
-    AVOptionRanges *ranges = *rangesp;
-
-    if (!ranges)
-        return;
-
-    for (i = 0; i < ranges->nb_ranges * ranges->nb_components; i++) {
-        AVOptionRange *range = ranges->range[i];
-        if (range) {
-            av_freep(&range->str);
-            av_freep(&ranges->range[i]);
-        }
-    }
-    av_freep(&ranges->range);
-    av_freep(rangesp);
-}
-
-int av_opt_is_set_to_default(void *obj, const AVOption *o)
-{
-    int64_t i64;
-    double d, d2;
-    float f;
-    AVRational q;
-    int ret, w, h;
-    char *str;
-    void *dst;
-
-    if (!o || !obj)
-        return AVERROR(EINVAL);
-
-    dst = ((uint8_t*)obj) + o->offset;
-
-    switch (o->type) {
-    case AV_OPT_TYPE_CONST:
-        return 1;
-    case AV_OPT_TYPE_BOOL:
-    case AV_OPT_TYPE_FLAGS:
-    case AV_OPT_TYPE_PIXEL_FMT:
-    case AV_OPT_TYPE_SAMPLE_FMT:
-    case AV_OPT_TYPE_INT:
-    case AV_OPT_TYPE_CHANNEL_LAYOUT:
-    case AV_OPT_TYPE_DURATION:
-    case AV_OPT_TYPE_INT64:
-        read_number(o, dst, NULL, NULL, &i64);
-        return o->default_val.i64 == i64;
-    case AV_OPT_TYPE_STRING:
-        str = *(char **)dst;
-        if (str == o->default_val.str) //2 NULLs
-            return 1;
-        if (!str || !o->default_val.str) //1 NULL
-            return 0;
-        return !strcmp(str, o->default_val.str);
-    case AV_OPT_TYPE_DOUBLE:
-        read_number(o, dst, &d, NULL, NULL);
-        return o->default_val.dbl == d;
-    case AV_OPT_TYPE_FLOAT:
-        read_number(o, dst, &d, NULL, NULL);
-        f = o->default_val.dbl;
-        d2 = f;
-        return d2 == d;
-    case AV_OPT_TYPE_RATIONAL:
-        q = av_d2q(o->default_val.dbl, INT_MAX);
-        return !av_cmp_q(*(AVRational*)dst, q);
-    case AV_OPT_TYPE_BINARY: {
-        struct {
-            uint8_t *data;
-            int size;
-        } tmp = {0};
-        int opt_size = *(int *)((void **)dst + 1);
-        void *opt_ptr = *(void **)dst;
-        if (!opt_size && (!o->default_val.str || !strlen(o->default_val.str)))
-            return 1;
-        if (!opt_size ||  !o->default_val.str || !strlen(o->default_val.str ))
-            return 0;
-        if (opt_size != strlen(o->default_val.str) / 2)
-            return 0;
-        ret = set_string_binary(NULL, NULL, o->default_val.str, &tmp.data);
-        if (!ret)
-            ret = !memcmp(opt_ptr, tmp.data, tmp.size);
-        av_free(tmp.data);
-        return ret;
-    }
-    case AV_OPT_TYPE_DICT:
-        /* Binary and dict have not default support yet. Any pointer is not default. */
-        return !!(*(void **)dst);
-    case AV_OPT_TYPE_IMAGE_SIZE:
-        if (!o->default_val.str || !strcmp(o->default_val.str, "none"))
-            w = h = 0;
-        else if ((ret = av_parse_video_size(&w, &h, o->default_val.str)) < 0)
-            return ret;
-        return (w == *(int *)dst) && (h == *((int *)dst+1));
-    case AV_OPT_TYPE_VIDEO_RATE:
-        q = (AVRational){0, 0};
-        if (o->default_val.str) {
-            if ((ret = av_parse_video_rate(&q, o->default_val.str)) < 0)
-                return ret;
-        }
-        return !av_cmp_q(*(AVRational*)dst, q);
-    case AV_OPT_TYPE_COLOR: {
-        uint8_t color[4] = {0, 0, 0, 0};
-        if (o->default_val.str) {
-            if ((ret = av_parse_color(color, o->default_val.str, -1, NULL)) < 0)
-                return ret;
-        }
-        return !memcmp(color, dst, sizeof(color));
-    }
-    default:
-        av_log(obj, AV_LOG_WARNING, "Not supported option type: %d, option name: %s\n", o->type, o->name);
-        break;
-    }
-    return AVERROR_PATCHWELCOME;
-}
-
-int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags)
-{
-    const AVOption *o;
-    void *target;
-    if (!obj)
-        return AVERROR(EINVAL);
-    o = av_opt_find2(obj, name, NULL, 0, search_flags, &target);
-    if (!o)
-        return AVERROR_OPTION_NOT_FOUND;
-    return av_opt_is_set_to_default(target, o);
-}
-
-int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
-                     const char key_val_sep, const char pairs_sep)
-{
-    const AVOption *o = NULL;
-    uint8_t *buf;
-    AVBPrint bprint;
-    int ret, cnt = 0;
-    const char special_chars[] = {pairs_sep, key_val_sep, '\0'};
-
-    if (pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
-        pairs_sep == '\\' || key_val_sep == '\\') {
-        av_log(obj, AV_LOG_ERROR, "Invalid separator(s) found.");
-        return AVERROR(EINVAL);
-    }
-
-    if (!obj || !buffer)
-        return AVERROR(EINVAL);
-
-    *buffer = NULL;
-    av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
-
-    while (o = av_opt_next(obj, o)) {
-        if (o->type == AV_OPT_TYPE_CONST)
-            continue;
-        if ((flags & AV_OPT_SERIALIZE_OPT_FLAGS_EXACT) && o->flags != opt_flags)
-            continue;
-        else if (((o->flags & opt_flags) != opt_flags))
-            continue;
-        if (flags & AV_OPT_SERIALIZE_SKIP_DEFAULTS && av_opt_is_set_to_default(obj, o) > 0)
-            continue;
-        if ((ret = av_opt_get(obj, o->name, 0, &buf)) < 0) {
-            av_bprint_finalize(&bprint, NULL);
-            return ret;
-        }
-        if (buf) {
-            if (cnt++)
-                av_bprint_append_data(&bprint, &pairs_sep, 1);
-            av_bprint_escape(&bprint, o->name, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
-            av_bprint_append_data(&bprint, &key_val_sep, 1);
-            av_bprint_escape(&bprint, buf, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
-            av_freep(&buf);
-        }
-    }
-    av_bprint_finalize(&bprint, buffer);
-    return 0;
-}
--- a/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageManager.java
+++ b/mobile/android/stumbler/java/org/mozilla/mozstumbler/service/stumblerthread/datahandling/DataStorageManager.java
@@ -262,17 +262,17 @@ public class DataStorageManager {
     }
 
     public synchronized boolean isDirEmpty() {
         return (mFileList.mFiles == null || mFileList.mFiles.length < 1);
     }
 
     /* Pass filename returned from dataToSend() */
     public synchronized boolean delete(String filename) {
-        if (filename == MEMORY_BUFFER_NAME) {
+        if (filename.equals(MEMORY_BUFFER_NAME)) {
             mCurrentReportsSendBuffer = null;
             return true;
         }
 
         final File file = new File(mReportsDir, filename);
         final boolean ok = file.delete();
         mFileList.update(mReportsDir);
         return ok;
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5497,8 +5497,13 @@ pref("media.seekToNextFrame.enabled", tr
 #if !defined(RELEASE_BUILD)
 pref("osfile.reset_worker_delay", 30000);
 #endif
 
 #if !defined(MOZ_WIDGET_GONK) && !defined(MOZ_WIDGET_ANDROID)
 pref("dom.webkitBlink.dirPicker.enabled", true);
 pref("dom.webkitBlink.filesystem.enabled", true);
 #endif
+
+#ifdef MOZ_STYLO
+// Is the Servo-backed style system enabled?
+pref("layout.css.servo.enabled", true);
+#endif
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -64,16 +64,17 @@ do {                             \
   return NS_ERROR_ILLEGAL_VALUE; \
   } while (0)
 
 Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t version)
   : mSocketTransport(aSocketTransport)
   , mSegmentReader(nullptr)
   , mSegmentWriter(nullptr)
   , mNextStreamID(3) // 1 is reserved for Updgrade handshakes
+  , mLastPushedID(0)
   , mConcurrentHighWater(0)
   , mDownstreamState(BUFFERING_OPENING_SETTINGS)
   , mInputFrameBufferSize(kDefaultBufferSize)
   , mInputFrameBufferUsed(0)
   , mInputFrameDataSize(0)
   , mInputFrameDataRead(0)
   , mInputFrameFinal(false)
   , mInputFrameType(0)
@@ -1547,16 +1548,22 @@ Http2Session::RecvPushPromise(Http2Sessi
     nsresult rv = self->ParsePadding(paddingControlBytes, paddingLength);
     if (NS_FAILED(rv)) {
       return rv;
     }
     promiseLen = 4;
     promisedID = NetworkEndian::readUint32(
         self->mInputFrameBuffer.get() + kFrameHeaderBytes + paddingControlBytes);
     promisedID &= 0x7fffffff;
+    if (promisedID <= self->mLastPushedID) {
+      LOG3(("Http2Session::RecvPushPromise %p ID too low %u expected > %u.\n",
+            self, promisedID, self->mLastPushedID));
+      RETURN_SESSION_ERROR(self, PROTOCOL_ERROR);
+    }
+    self->mLastPushedID = promisedID;
   }
 
   uint32_t associatedID = self->mInputFrameID;
 
   if (self->mInputFrameFlags & kFlag_END_PUSH_PROMISE) {
     self->mExpectedPushPromiseID = 0;
     self->mContinuedPromiseStream = 0;
   } else {
--- a/netwerk/protocol/http/Http2Session.h
+++ b/netwerk/protocol/http/Http2Session.h
@@ -312,16 +312,17 @@ private:
   // These are temporary state variables to hold the argument to
   // Read/WriteSegments so it can be accessed by On(read/write)segment
   // further up the stack.
   nsAHttpSegmentReader       *mSegmentReader;
   nsAHttpSegmentWriter       *mSegmentWriter;
 
   uint32_t          mSendingChunkSize;        /* the transmission chunk size */
   uint32_t          mNextStreamID;            /* 24 bits */
+  uint32_t          mLastPushedID;
   uint32_t          mConcurrentHighWater;     /* max parallelism on session */
   uint32_t          mPushAllowance;           /* rwin for unmatched pushes */
 
   internalStateType mDownstreamState; /* in frame, between frames, etc..  */
 
   // Maintain 2 indexes - one by stream ID, one by transaction pointer.
   // There are also several lists of streams: ready to write, queued due to
   // max parallelism, streams that need to force a read for push, and the full
--- a/testing/firefox-ui/tests/puppeteer/manifest.ini
+++ b/testing/firefox-ui/tests/puppeteer/manifest.ini
@@ -15,8 +15,9 @@ tags = remote
 [test_about_window.py]
 [test_menubar.py]
 [test_notifications.py]
 [test_page_info_window.py]
 [test_tabbar.py]
 [test_toolbars.py]
 tags = remote
 [test_windows.py]
+skip-if = e10s # Bug 1292471
--- a/testing/mozharness/mozharness/base/script.py
+++ b/testing/mozharness/mozharness/base/script.py
@@ -10,34 +10,29 @@
 script.py, along with config.py and log.py, represents the core of
 mozharness.
 """
 
 import codecs
 from contextlib import contextmanager
 import datetime
 import errno
-import fnmatch
-import functools
 import gzip
 import inspect
-import itertools
 import os
 import platform
 import pprint
 import re
 import shutil
 import socket
 import subprocess
 import sys
-import tarfile
 import time
 import traceback
 import urllib2
-import zipfile
 import httplib
 import urlparse
 import hashlib
 if os.name == 'nt':
     try:
         import win32file
         import win32api
         PYWIN32 = True
@@ -47,20 +42,20 @@ if os.name == 'nt':
 try:
     import simplejson as json
     assert json
 except ImportError:
     import json
 
 from mozprocess import ProcessHandler
 from mozharness.base.config import BaseConfig
+from mozharness.base.errors import ZipErrorList
 from mozharness.base.log import SimpleFileLogger, MultiFileLogger, \
     LogMixin, OutputParser, DEBUG, INFO, ERROR, FATAL
 
-
 def platform_name():
     pm = PlatformMixin()
 
     if pm._is_linux() and pm._is_64_bit():
         return 'linux64'
     elif pm._is_linux() and not pm._is_64_bit():
         return 'linux'
     elif pm._is_darwin():
@@ -453,38 +448,49 @@ class ScriptMixin(PlatformMixin):
             kwargs = {"url": url, "file_name": file_name}
 
         return self.retry(
             download_func,
             kwargs=kwargs,
             **retry_args
         )
 
-    def download_unpack(self, url, extract_to, extract_dirs=None,
-                        error_level=FATAL):
-        """Generic method to download and extract a compressed file.
+    def download_unzip(self, url, parent_dir, target_unzip_dirs=None, halt_on_failure=True):
+        """Generic method to download and extract a zip file.
 
         The downloaded file will always be saved to the working directory and is not getting
         deleted after extracting.
 
         Args:
             url (str): URL where the file to be downloaded is located.
-            extract_to (str): directory where the downloaded file will
+            parent_dir (str): directory where the downloaded file will
                               be extracted to.
-            extract_dirs (list, optional): directories inside the archive to extract.
-                                           Defaults to `None`.
-            error_level (str, optional): log level to use in case an error occurs.
-                                         Defaults to `FATAL`.
+            target_unzip_dirs (list, optional): directories inside the zip file to extract.
+                                                Defaults to `None`.
+            halt_on_failure (bool, optional): whether or not to redefine the
+                                              log level as `FATAL` on errors. Defaults to True.
 
         """
         dirs = self.query_abs_dirs()
-        archive = self.download_file(url, parent_dir=dirs['abs_work_dir'],
-                                     error_level=error_level)
-        self.unpack(archive, extract_to, extract_dirs=extract_dirs,
-                    error_level=error_level)
+        zipfile = self.download_file(url, parent_dir=dirs['abs_work_dir'],
+                                     error_level=FATAL)
+
+        command = self.query_exe('unzip', return_type='list')
+        # Always overwrite to not get an input in a hidden pipe if files already exist
+        command.extend(['-q', '-o', zipfile, '-d', parent_dir])
+        if target_unzip_dirs:
+            command.extend(target_unzip_dirs)
+        # TODO error_list: http://www.info-zip.org/mans/unzip.html#DIAGNOSTICS
+        # unzip return code 11 is 'no matching files were found'
+        self.run_command(command,
+                         error_list=ZipErrorList,
+                         halt_on_failure=halt_on_failure,
+                         fatal_exit_code=3,
+                         success_codes=[0, 11],
+                         )
 
     def load_json_url(self, url, error_level=None, *args, **kwargs):
         """ Returns a json object from a url (it retries). """
         contents = self._retry_download(
             url=url, error_level=error_level, *args, **kwargs
         )
         return json.loads(contents.read())
 
@@ -1094,17 +1100,17 @@ class ScriptMixin(PlatformMixin):
             throw_exception (bool, optional): whether or not to raise an
               exception if the return value of the command doesn't match
               any of the `success_codes`. Defaults to False.
             output_parser (OutputParser, optional): lets you provide an
               instance of your own OutputParser subclass. Defaults to `OutputParser`.
             output_timeout (int): amount of seconds to wait for output before
               the process is killed.
             fatal_exit_code (int, optional): call `self.fatal` if the return value
-              of the command is not in `success_codes`. Defaults to 2.
+              of the command is not on in `success_codes`. Defaults to 2.
             error_level (str, optional): log level name to use on error. Defaults
               to `ERROR`.
             **kwargs: Arbitrary keyword arguments.
 
         Returns:
             int: -1 on error.
             Any: `command` return value is returned otherwise.
         """
@@ -1386,79 +1392,36 @@ class ScriptMixin(PlatformMixin):
         except OSError:
             try:
                 open(file_name, 'w').close()
             except IOError as e:
                 msg = "I/O error(%s): %s" % (e.errno, e.strerror)
                 self.log(msg, error_level=error_level)
         os.utime(file_name, times)
 
-    def unpack(self, filename, extract_to, extract_dirs=None,
-               error_level=ERROR, fatal_exit_code=2, verbose=False):
-        """The method allows to extract a file regardless of its extension.
+    def unpack(self, filename, extract_to):
+        '''
+        This method allows us to extract a file regardless of its extension
 
         Args:
             filename (str): filename of the compressed file.
             extract_to (str): where to extract the compressed file.
-            extract_dirs (list, optional): directories inside the archive file to extract.
-                                           Defaults to `None`.
-            fatal_exit_code (int, optional): call `self.fatal` if the return value
-              of the command is not in `success_codes`. Defaults to 2.
-            verbose (bool, optional): whether or not extracted content should be displayed.
-                                      Defaults to False.
-
-        Raises:
-            IOError: on `filename` file not found.
-
-        """
-        def _filter_entries(namelist):
-            """Filter entries of the archive based on the specified list of to extract dirs."""
-            filter_partial = functools.partial(fnmatch.filter, namelist)
-            for entry in itertools.chain(*map(filter_partial, extract_dirs or ['*'])):
-                yield entry
-
-        if not os.path.isfile(filename):
-            raise IOError('Could not find file to extract: %s' % filename)
-
-        if zipfile.is_zipfile(filename):
-            try:
-                self.info('Using ZipFile to extract {} to {}'.format(filename, extract_to))
-                with zipfile.ZipFile(filename) as bundle:
-                    for entry in _filter_entries(bundle.namelist()):
-                        if verbose:
-                            self.info(' %s' % entry)
-                        bundle.extract(entry, path=extract_to)
-
-                        # ZipFile doesn't preserve permissions during extraction:
-                        # http://bugs.python.org/issue15795
-                        fname = os.path.realpath(os.path.join(extract_to, entry))
-                        mode = bundle.getinfo(entry).external_attr >> 16 & 0x1FF
-                        # Only set permissions if attributes are available. Otherwise all
-                        # permissions will be removed eg. on Windows.
-                        if mode:
-                            os.chmod(fname, mode)
-            except zipfile.BadZipfile as e:
-                self.log('%s (%s)' % (e.message, filename),
-                         level=error_level, exit_code=fatal_exit_code)
-
-        # Bug 1211882 - is_tarfile cannot be trusted for dmg files
-        elif tarfile.is_tarfile(filename) and not filename.lower().endswith('.dmg'):
-            try:
-                self.info('Using TarFile to extract {} to {}'.format(filename, extract_to))
-                with tarfile.open(filename) as bundle:
-                    for entry in _filter_entries(bundle.getnames()):
-                        if verbose:
-                            self.info(' %s' % entry)
-                        bundle.extract(entry, path=extract_to)
-            except tarfile.TarError as e:
-                self.log('%s (%s)' % (e.message, filename),
-                         level=error_level, exit_code=fatal_exit_code)
+        '''
+        # XXX: Make sure that filename has a extension of one of our supported file formats
+        m = re.search('\.tar\.(bz2|gz)$', filename)
+        if m:
+            command = self.query_exe('tar', return_type='list')
+            tar_cmd = "jxfv"
+            if m.group(1) == "gz":
+                tar_cmd = "zxfv"
+            command.extend([tar_cmd, filename, "-C", extract_to])
+            self.run_command(command, halt_on_failure=True)
         else:
-            self.log('No extraction method found for: %s' % filename,
-                     level=error_level, exit_code=fatal_exit_code)
+            # XXX implement
+            pass
 
 
 def PreScriptRun(func):
     """Decorator for methods that will be called before script execution.
 
     Each method on a BaseScript having this decorator will be called at the
     beginning of BaseScript.run().
 
--- a/testing/mozharness/mozharness/mozilla/testing/firefox_media_tests.py
+++ b/testing/mozharness/mozharness/mozilla/testing/firefox_media_tests.py
@@ -158,24 +158,25 @@ class FirefoxMediaTestsBase(TestingMixin
 
     def download_and_extract(self):
         """Overriding method from TestingMixin for more specific behavior.
 
         We use the test_packages_url command line argument to check where to get the
         harness, puppeteer, and tests from and how to set them up.
 
         """
-        extract_dirs = ['config/*',
-                        'external-media-tests/*',
-                        'marionette/*',
-                        'mozbase/*',
-                        'puppeteer/*',
-                        'tools/wptserve/*',
-                        ]
-        super(FirefoxMediaTestsBase, self).download_and_extract(extract_dirs=extract_dirs)
+        target_unzip_dirs = ['config/*',
+                             'external-media-tests/*',
+                             'marionette/*',
+                             'mozbase/*',
+                             'puppeteer/*',
+                             'tools/wptserve/*',
+                             ]
+        super(FirefoxMediaTestsBase, self).download_and_extract(
+                target_unzip_dirs=target_unzip_dirs)
 
     def query_abs_dirs(self):
         if self.abs_dirs:
             return self.abs_dirs
         abs_dirs = super(FirefoxMediaTestsBase, self).query_abs_dirs()
         dirs = {
             'abs_test_install_dir' : os.path.join(abs_dirs['abs_work_dir'],
                                                     'tests')
--- a/testing/mozharness/mozharness/mozilla/testing/firefox_ui_tests.py
+++ b/testing/mozharness/mozharness/mozilla/testing/firefox_ui_tests.py
@@ -148,24 +148,24 @@ class FirefoxUITests(TestingMixin, VCSTo
 
     def download_and_extract(self):
         """Overriding method from TestingMixin for more specific behavior.
 
         We use the test_packages_url command line argument to check where to get the
         harness, puppeteer, and tests from and how to set them up.
 
         """
-        extract_dirs = ['config/*',
-                        'firefox-ui/*',
-                        'marionette/*',
-                        'mozbase/*',
-                        'puppeteer/*',
-                        'tools/wptserve/*',
-                        ]
-        super(FirefoxUITests, self).download_and_extract(extract_dirs=extract_dirs)
+        target_unzip_dirs = ['config/*',
+                             'firefox-ui/*',
+                             'marionette/*',
+                             'mozbase/*',
+                             'puppeteer/*',
+                             'tools/wptserve/*',
+                             ]
+        super(FirefoxUITests, self).download_and_extract(target_unzip_dirs=target_unzip_dirs)
 
     def query_abs_dirs(self):
         if self.abs_dirs:
             return self.abs_dirs
 
         abs_dirs = super(FirefoxUITests, self).query_abs_dirs()
         abs_tests_install_dir = os.path.join(abs_dirs['abs_work_dir'], 'tests')
 
@@ -294,16 +294,63 @@ class FirefoxUITests(TestingMixin, VCSTo
 
     def run_tests(self):
         """Run all the tests"""
         return self.run_test(
             binary_path=self.binary_path,
             env=self.query_env(),
         )
 
+    def download_unzip(self, url, parent_dir, target_unzip_dirs=None, halt_on_failure=True):
+        """Overwritten method from BaseScript until bug 1258539 is fixed.
+
+        The downloaded file will always be saved to the working directory and is not getting
+        deleted after extracting.
+
+        Args:
+            url (str): URL where the file to be downloaded is located.
+            parent_dir (str): directory where the downloaded file will
+                              be extracted to.
+            target_unzip_dirs (list, optional): directories inside the zip file to extract.
+                                                Defaults to `None`.
+            halt_on_failure (bool, optional): whether or not to redefine the
+                                              log level as `FATAL` on errors. Defaults to True.
+
+        """
+        import fnmatch
+        import itertools
+        import functools
+        import zipfile
+
+        def _filter_entries(namelist):
+            """Filter entries of the archive based on the specified list of extract_dirs."""
+            filter_partial = functools.partial(fnmatch.filter, namelist)
+            for entry in itertools.chain(*map(filter_partial, target_unzip_dirs or ['*'])):
+                yield entry
+
+        dirs = self.query_abs_dirs()
+        zip = self.download_file(url, parent_dir=dirs['abs_work_dir'],
+                                 error_level=FATAL)
+
+        try:
+            self.info('Using ZipFile to extract {0} to {1}'.format(zip, parent_dir))
+            with zipfile.ZipFile(zip) as bundle:
+                for entry in _filter_entries(bundle.namelist()):
+                    bundle.extract(entry, path=parent_dir)
+
+                    # ZipFile doesn't preserve permissions: http://bugs.python.org/issue15795
+                    fname = os.path.realpath(os.path.join(parent_dir, entry))
+                    mode = bundle.getinfo(entry).external_attr >> 16 & 0x1FF
+                    # Only set permissions if attributes are available.
+                    if mode:
+                        os.chmod(fname, mode)
+        except zipfile.BadZipfile as e:
+            self.log('{0} ({1})'.format(e.message, zip),
+                     level=FATAL, exit_code=2)
+
 
 class FirefoxUIFunctionalTests(FirefoxUITests):
 
     cli_script = 'cli_functional.py'
     default_tests = [
         os.path.join('puppeteer', 'manifest.ini'),
         os.path.join('functional', 'manifest.ini'),
     ]
--- a/testing/mozharness/mozharness/mozilla/testing/talos.py
+++ b/testing/mozharness/mozharness/mozilla/testing/talos.py
@@ -282,23 +282,23 @@ class Talos(TestingMixin, MercurialScrip
         if c.get('run_local'):
             self.talos_path = os.path.dirname(self.talos_json)
 
         src_talos_webdir = os.path.join(self.talos_path, 'talos')
 
         if self.query_pagesets_url():
             self.info("Downloading pageset...")
             src_talos_pageset = os.path.join(src_talos_webdir, 'tests')
-            self.download_unpack(self.pagesets_url, src_talos_pageset)
+            self.download_unzip(self.pagesets_url, src_talos_pageset)
 
     # Action methods. {{{1
     # clobber defined in BaseScript
     # read_buildbot_config defined in BuildbotMixin
 
-    def download_and_extract(self, extract_dirs=None, suite_categories=None):
+    def download_and_extract(self, target_unzip_dirs=None, suite_categories=None):
         return super(Talos, self).download_and_extract(
             suite_categories=['common', 'talos']
         )
 
     def create_virtualenv(self, **kwargs):
         """VirtualenvMixin.create_virtualenv() assuemes we're using
         self.config['virtualenv_modules']. Since we are installing
         talos from its source, we have to wrap that method here."""
--- a/testing/mozharness/mozharness/mozilla/testing/testbase.py
+++ b/testing/mozharness/mozharness/mozilla/testing/testbase.py
@@ -396,16 +396,27 @@ You can set this by:
 
 1. specifying --test-url URL, or
 2. running via buildbot and running the read-buildbot-config action
 
 """
         if message:
             self.fatal(message + "Can't run download-and-extract... exiting")
 
+        if self.config.get("developer_mode") and self._is_darwin():
+            # Bug 1066700 only affects Mac users that try to run mozharness locally
+            version = self._query_binary_version(
+                    regex=re.compile("UnZip\ (\d+\.\d+)\ .*", re.MULTILINE),
+                    cmd=[self.query_exe('unzip'), '-v']
+            )
+            if not version >= 6:
+                self.fatal("We require a more recent version of unzip to unpack our tests.zip files.\n"
+                        "You are currently using version %s. Please update to at least 6.0.\n"
+                        "You can visit http://www.info-zip.org/UnZip.html" % version)
+
     def _read_packages_manifest(self):
         dirs = self.query_abs_dirs()
         source = self.download_file(self.test_packages_url,
                                     parent_dir=dirs['abs_work_dir'],
                                     error_level=FATAL)
 
         with self.opened(os.path.realpath(source)) as (fh, err):
             package_requirements = json.load(fh)
@@ -413,17 +424,17 @@ 2. running via buildbot and running the 
                 self.fatal("There was an error reading test package requirements from %s "
                            "requirements: `%s` - error: `%s`" % (source,
                                                                  package_requirements or 'None',
                                                                  err or 'No error'))
         self.info("Using the following test package requirements:\n%s" %
                   pprint.pformat(package_requirements))
         return package_requirements
 
-    def _download_test_packages(self, suite_categories, extract_dirs):
+    def _download_test_packages(self, suite_categories, target_unzip_dirs):
         # Some platforms define more suite categories/names than others.
         # This is a difference in the convention of the configs more than
         # to how these tests are run, so we pave over these differences here.
         aliases = {
             'robocop': 'mochitest',
             'mochitest-chrome': 'mochitest',
             'mochitest-media': 'mochitest',
             'mochitest-plain-clipboard': 'mochitest',
@@ -449,31 +460,31 @@ 2. running via buildbot and running the 
                 # If we don't harness specific requirements, assume the common zip
                 # has everything we need to run tests for this suite.
                 target_packages = package_requirements['common']
 
             self.info("Downloading packages: %s for test suite category: %s" %
                       (target_packages, category))
             for file_name in target_packages:
                 target_dir = test_install_dir
-                unpack_dirs = extract_dirs
+                unzip_dirs = target_unzip_dirs
                 if "jsshell-" in file_name or file_name == "target.jsshell.zip":
                     self.info("Special-casing the jsshell zip file")
-                    unpack_dirs = None
+                    unzip_dirs = None
                     target_dir = dirs['abs_test_bin_dir']
                 url = self.query_build_dir_url(file_name)
-                self.download_unpack(url, target_dir,
-                                     extract_dirs=unpack_dirs)
+                self.download_unzip(url, target_dir,
+                                     target_unzip_dirs=unzip_dirs)
 
-    def _download_test_zip(self, extract_dirs=None):
+    def _download_test_zip(self, target_unzip_dirs=None):
         dirs = self.query_abs_dirs()
         test_install_dir = dirs.get('abs_test_install_dir',
                                     os.path.join(dirs['abs_work_dir'], 'tests'))
-        self.download_unpack(self.test_url, test_install_dir,
-                             extract_dirs=extract_dirs)
+        self.download_unzip(self.test_url, test_install_dir,
+                             target_unzip_dirs=target_unzip_dirs)
 
     def structured_output(self, suite_category):
         """Defines whether structured logging is in use in this configuration. This
         may need to be replaced with data from a different config at the resolution
         of bug 1070041 and related bugs.
         """
         return ('structured_suites' in self.config and
                 suite_category in self.config['structured_suites'])
@@ -510,19 +521,19 @@ 2. running via buildbot and running the 
         if self.config.get('download_symbols') == 'ondemand':
             self.symbols_path = self.symbols_url
             return
         if not self.symbols_path:
             self.symbols_path = os.path.join(dirs['abs_work_dir'], 'symbols')
 
         self.set_buildbot_property("symbols_url", self.symbols_url,
                                    write_to_file=True)
-        self.download_unpack(self.symbols_url, self.symbols_path)
+        self.download_unzip(self.symbols_url, self.symbols_path)
 
-    def download_and_extract(self, extract_dirs=None, suite_categories=None):
+    def download_and_extract(self, target_unzip_dirs=None, suite_categories=None):
         """
         download and extract test zip / download installer
         """
         # Swap plain http for https when we're downloading from ftp
         # See bug 957502 and friends
         from_ = "http://ftp.mozilla.org"
         to_ = "https://ftp-ssl.mozilla.org"
         for attr in 'symbols_url', 'installer_url', 'test_packages_url', 'test_url':
@@ -535,27 +546,27 @@ 2. running via buildbot and running the 
         if 'test_url' in self.config:
             # A user has specified a test_url directly, any test_packages_url will
             # be ignored.
             if self.test_packages_url:
                 self.error('Test data will be downloaded from "%s", the specified test '
                            ' package data at "%s" will be ignored.' %
                            (self.config.get('test_url'), self.test_packages_url))
 
-            self._download_test_zip(extract_dirs)
+            self._download_test_zip(target_unzip_dirs)
         else:
             if not self.test_packages_url:
                 # The caller intends to download harness specific packages, but doesn't know
                 # where the packages manifest is located. This is the case when the
                 # test package manifest isn't set as a buildbot property, which is true
                 # for some self-serve jobs and platforms using parse_make_upload.
                 self.test_packages_url = self.query_prefixed_build_dir_url('.test_packages.json')
 
             suite_categories = suite_categories or ['common']
-            self._download_test_packages(suite_categories, extract_dirs)
+            self._download_test_packages(suite_categories, target_unzip_dirs)
 
         self._download_installer()
         if self.config.get('download_symbols'):
             self._download_and_extract_symbols()
 
     # create_virtualenv is in VirtualenvMixin.
 
     def preflight_install(self):
--- a/testing/mozharness/mozharness/mozilla/testing/unittest.py
+++ b/testing/mozharness/mozharness/mozilla/testing/unittest.py
@@ -230,17 +230,17 @@ class EmulatorMixin(object):
             unzip_cmd = [unzip, '-q', os.path.join(dirs['abs_work_dir'], "emulator.zip")]
             self.run_command(unzip_cmd, cwd=dirs['abs_emulator_dir'], halt_on_failure=True,
                              fatal_exit_code=3)
 
     def install_emulator(self):
         dirs = self.query_abs_dirs()
         self.mkdir_p(dirs['abs_emulator_dir'])
         if self.config.get('emulator_url'):
-            self.download_unpack(self.config['emulator_url'], dirs['abs_emulator_dir'])
+            self.download_unzip(self.config['emulator_url'], dirs['abs_emulator_dir'])
         elif self.config.get('emulator_manifest'):
             manifest_path = self.create_tooltool_manifest(self.config['emulator_manifest'])
             do_unzip = True
             if 'unpack' in self.config['emulator_manifest']:
                 do_unzip = False
             self.install_emulator_from_tooltool(manifest_path, do_unzip)
         elif self.buildbot_config:
             props = self.buildbot_config.get('properties')
--- a/testing/mozharness/scripts/b2g_emulator_unittest.py
+++ b/testing/mozharness/scripts/b2g_emulator_unittest.py
@@ -206,17 +206,18 @@ class B2GEmulatorTest(TestingMixin, VCSM
 
         self.mkdir_p(dirs['abs_emulator_dir'])
         tar = self.query_exe('tar', return_type='list')
         self.run_command(tar + ['zxf', self.installer_path],
                          cwd=dirs['abs_emulator_dir'],
                          error_list=TarErrorList,
                          halt_on_failure=True, fatal_exit_code=3)
 
-        self.download_unpack(self.config['xre_url'], dirs['abs_xre_dir'])
+        self.download_unzip(self.config['xre_url'],
+                             dirs['abs_xre_dir'])
 
         if self.config.get('busybox_url'):
             self.download_file(self.config['busybox_url'],
                                file_name='busybox',
                                parent_dir=dirs['abs_work_dir'])
             self.busybox_path = os.path.join(dirs['abs_work_dir'], 'busybox')
 
     @PreScriptAction('create-virtualenv')
--- a/testing/mozharness/scripts/desktop_unittest.py
+++ b/testing/mozharness/scripts/desktop_unittest.py
@@ -475,30 +475,30 @@ class DesktopUnittest(TestingMixin, Merc
 
     def download_and_extract(self):
         """
         download and extract test zip / download installer
         optimizes which subfolders to extract from tests zip
         """
         c = self.config
 
-        extract_dirs = None
+        target_unzip_dirs = None
         if c['specific_tests_zip_dirs']:
-            extract_dirs = list(c['minimum_tests_zip_dirs'])
+            target_unzip_dirs = list(c['minimum_tests_zip_dirs'])
             for category in c['specific_tests_zip_dirs'].keys():
                 if c['run_all_suites'] or self._query_specified_suites(category) \
                         or 'run-tests' not in self.actions:
-                    extract_dirs.extend(c['specific_tests_zip_dirs'][category])
+                    target_unzip_dirs.extend(c['specific_tests_zip_dirs'][category])
 
         if c.get('run_all_suites'):
             target_categories = SUITE_CATEGORIES
         else:
             target_categories = [cat for cat in SUITE_CATEGORIES
                                  if self._query_specified_suites(cat) is not None]
-        super(DesktopUnittest, self).download_and_extract(extract_dirs=extract_dirs,
+        super(DesktopUnittest, self).download_and_extract(target_unzip_dirs=target_unzip_dirs,
                                                           suite_categories=target_categories)
 
     def stage_files(self):
         for category in SUITE_CATEGORIES:
             suites = self._query_specified_suites(category)
             stage = getattr(self, '_stage_{}'.format(category), None)
             if suites and stage:
                 stage(suites)
--- a/testing/mozharness/scripts/web_platform_tests.py
+++ b/testing/mozharness/scripts/web_platform_tests.py
@@ -161,22 +161,22 @@ class WebPlatformTest(TestingMixin, Merc
                                       str_format_values=str_format_values))
         cmd.extend(self.query_tests_args(try_tests,
                                          str_format_values=str_format_values))
 
         return cmd
 
     def download_and_extract(self):
         super(WebPlatformTest, self).download_and_extract(
-            extract_dirs=["bin/*",
-                          "config/*",
-                          "mozbase/*",
-                          "marionette/*",
-                          "tools/wptserve/*",
-                          "web-platform/*"],
+            target_unzip_dirs=["bin/*",
+                               "config/*",
+                               "mozbase/*",
+                               "marionette/*",
+                               "tools/wptserve/*",
+                               "web-platform/*"],
             suite_categories=["web-platform"])
 
     def run_tests(self):
         dirs = self.query_abs_dirs()
         cmd = self._query_cmd()
 
         parser = StructuredOutputParser(config=self.config,
                                         log_obj=self.log_obj,
deleted file mode 100644
index 1dc094198f3198c38e6c04dd9ea98dacecced1e1..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index c393ea4b881cc0ce9bd4d05e2368a162f4da9d78..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 0fbfa39b1c76ae868fc8b67d3c76d199fd0c24eb..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index aa2fb34c1658128d6a25f0f40b5ae646b198ea7b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 20bdc5acdf11e3c466c5b59090d1aaa52b721d31..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100755
--- a/testing/mozharness/test/helper_files/archives/reference/bin/script.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-echo Hello world!
deleted file mode 100644
--- a/testing/mozharness/test/helper_files/archives/reference/lorem.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-Lorem ipsum dolor sit amet.
deleted file mode 100755
--- a/testing/mozharness/test/helper_files/create_archives.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-# Script to auto-generate the different archive types under the archives directory.
-
-cd archives
-
-rm archive.*
-
-tar cf archive.tar -C reference .
-gzip -fk archive.tar >archive.tar.gz
-bzip2 -fk archive.tar >archive.tar.bz2
-cd reference && zip ../archive.zip -r * && cd ..
--- a/testing/mozharness/test/test_base_script.py
+++ b/testing/mozharness/test/test_base_script.py
@@ -1,14 +1,12 @@
 import gc
 import mock
 import os
 import re
-import shutil
-import tempfile
 import types
 import unittest
 PYWIN32 = False
 if os.name == 'nt':
     try:
         import win32file
         PYWIN32 = True
     except:
@@ -16,37 +14,32 @@ if os.name == 'nt':
 
 
 import mozharness.base.errors as errors
 import mozharness.base.log as log
 from mozharness.base.log import DEBUG, INFO, WARNING, ERROR, CRITICAL, FATAL, IGNORE
 import mozharness.base.script as script
 from mozharness.base.config import parse_config_file
 
-
-here = os.path.dirname(os.path.abspath(__file__))
-
 test_string = '''foo
 bar
 baz'''
 
 
 class CleanupObj(script.ScriptMixin, log.LogMixin):
     def __init__(self):
         super(CleanupObj, self).__init__()
         self.log_obj = None
         self.config = {'log_level': ERROR}
 
 
-def cleanup(files=None):
-    files = files or []
-    files.extend(('test_logs', 'test_dir', 'tmpfile_stdout', 'tmpfile_stderr'))
+def cleanup():
     gc.collect()
     c = CleanupObj()
-    for f in files:
+    for f in ('test_logs', 'test_dir', 'tmpfile_stdout', 'tmpfile_stderr'):
         c.rmtree(f)
 
 
 def get_debug_script_obj():
     s = script.BaseScript(config={'log_type': 'multi',
                                   'log_level': DEBUG},
                           initial_config_file='test/test.json')
     return s
@@ -58,23 +51,22 @@ def _post_fatal(self, **kwargs):
     fh.close()
 
 
 # TestScript {{{1
 class TestScript(unittest.TestCase):
     def setUp(self):
         cleanup()
         self.s = None
-        self.tmpdir = tempfile.mkdtemp(suffix='.mozharness')
 
     def tearDown(self):
         # Close the logfile handles, or windows can't remove the logs
         if hasattr(self, 's') and isinstance(self.s, object):
             del(self.s)
-        cleanup([self.tmpdir])
+        cleanup()
 
     # test _dump_config_hierarchy() when --dump-config-hierarchy is passed
     def test_dump_config_hierarchy_valid_files_len(self):
         try:
             self.s = script.BaseScript(
                 initial_config_file='test/test.json',
                 option_args=['--cfg', 'test/test_override.py,test/test_override2.py'],
                 config={'dump_config_hierarchy': True}
@@ -254,48 +246,16 @@ class TestScript(unittest.TestCase):
                 'regex': re.compile(',$'), 'level': IGNORE,
             }, {
                 'substr': ']$', 'level': WARNING,
             }])
         error_logsize = os.path.getsize("test_logs/test_error.log")
         self.assertTrue(error_logsize > 0,
                         msg="error list not working properly")
 
-    def test_unpack(self):
-        self.s = get_debug_script_obj()
-
-        archives_path = os.path.join(here, 'helper_files', 'archives')
-
-        # Test basic decompression
-        for archive in ('archive.tar', 'archive.tar.bz2', 'archive.tar.gz', 'archive.zip'):
-            self.s.unpack(os.path.join(archives_path, archive), self.tmpdir)
-            self.assertIn('script.sh', os.listdir(os.path.join(self.tmpdir, 'bin')))
-            self.assertIn('lorem.txt', os.listdir(self.tmpdir))
-            shutil.rmtree(self.tmpdir)
-
-        # Test permissions for extracted entries from zip archive
-        self.s.unpack(os.path.join(archives_path, 'archive.zip'), self.tmpdir)
-        file_stats = os.stat(os.path.join(self.tmpdir, 'bin', 'script.sh'))
-        orig_fstats = os.stat(os.path.join(archives_path, 'reference', 'bin', 'script.sh'))
-        self.assertEqual(file_stats.st_mode, orig_fstats.st_mode)
-        shutil.rmtree(self.tmpdir)
-
-        # Test extract specific dirs only
-        self.s.unpack(os.path.join(archives_path, 'archive.zip'), self.tmpdir,
-                      extract_dirs=['bin/*'])
-        self.assertIn('bin', os.listdir(self.tmpdir))
-        self.assertNotIn('lorem.txt', os.listdir(self.tmpdir))
-        shutil.rmtree(self.tmpdir)
-
-        # Test for invalid filenames (Windows only)
-        if PYWIN32:
-            with self.assertRaises(IOError):
-                self.s.unpack(os.path.join(archives_path, 'archive_invalid_filename.zip'),
-                              self.tmpdir)
-
 
 # TestHelperFunctions {{{1
 class TestHelperFunctions(unittest.TestCase):
     temp_file = "test_dir/mozilla"
 
     def setUp(self):
         cleanup()
         self.s = None
deleted file mode 100644
--- a/testing/web-platform/meta/XMLHttpRequest/send-accept.htm.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[send-accept.htm]
-  type: testharness
-  [XMLHttpRequest: send() - Accept]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/html/semantics/forms/textfieldselection/selection.html.ini
+++ /dev/null
@@ -1,18 +0,0 @@
-[selection.html]
-  type: testharness
-  [test SelectionStart offset for input]
-    expected: FAIL
-    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1287655
-
-  [test SelectionStart offset for textarea]
-    expected: FAIL
-    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1287655
-
-  [test SelectionEnd offset for input]
-    expected: FAIL
-    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1287655
-
-  [test SelectionEnd offset for textarea]
-    expected: FAIL
-    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1287655
-
--- a/testing/web-platform/meta/media-source/mediasource-preload.html.ini
+++ b/testing/web-platform/meta/media-source/mediasource-preload.html.ini
@@ -1,12 +1,9 @@
 [mediasource-preload.html]
   type: testharness
   expected: TIMEOUT
-  [sourceopen occurs with element preload=none]
-    expected: TIMEOUT
-
   [error occurs with bogus blob URL (revoked MediaSource object URL) and element preload=none]
     expected: TIMEOUT
 
   [error occurs with bogus blob URL (corrupted MediaSource object URL) and element preload=none]
     expected: TIMEOUT
 
--- a/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm
@@ -163,25 +163,25 @@ indexeddb_test(
     function(t, db, txn) {
         var store = setup_test_store(db);
         var cursor_rq = store.openCursor();
         var cursor;
 
         cursor_rq.onerror = t.unreached_func('openCursor should succeed');
         cursor_rq.onsuccess = t.step_func(function(e) {
             if (!cursor) {
-	            cursor = e.target.result;
-	            assert_true(!!cursor, "acquire cursor");
+                cursor = e.target.result;
+                assert_true(!!cursor, "acquire cursor");
 
-	            cursor.continue();
+                cursor.continue();
 
-	            assert_throws("InvalidAccessError", function() {
-	                cursor.continuePrimaryKey("A", 4);
-	            }, "index source check should precede iteration ongoing check");
-	            t.done();
+                assert_throws("InvalidAccessError", function() {
+                    cursor.continuePrimaryKey("A", 4);
+                }, "index source check should precede iteration ongoing check");
+                t.done();
             }
         });
     },
     null,
     "InvalidAccessError(incorrect source) v.s. InvalidStateError(iteration ongoing)"
 );
 
 indexeddb_test(
@@ -196,45 +196,45 @@ indexeddb_test(
         cursor_rq.onerror = t.unreached_func('openCursor should succeed');
         cursor_rq.onsuccess = t.step_func(function(e) {
             if (e.target.result) {
                 cursor = e.target.result;
                 cursor.continue();
                 return;
             }
 
-	        assert_throws("InvalidAccessError", function() {
-	            cursor.continuePrimaryKey("A", 4);
-	        }, "index source check should precede got_value_flag check");
-	        t.done();
+            assert_throws("InvalidAccessError", function() {
+                cursor.continuePrimaryKey("A", 4);
+            }, "index source check should precede got_value_flag check");
+            t.done();
         });