merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 27 Jun 2016 11:58:47 +0200
changeset 342715 0e3f8401b804702c894eb5fdf7eae3cbdf618668
parent 342682 110c7ad7d399d16b9c77940f766a26df5d90f881 (current diff)
parent 342714 e68e0c28c1b1ed8ac55693f4fb0f6ebb14b74436 (diff)
child 342716 1d84194ace3538ad91d6cffb6fa3ec6a3a5037be
child 342730 3f257dd4c81aaa3ef5d4db262d1ffd7eadd3e7fe
child 342746 fccaa8ee3ed99b39aa47aa60ba6d5879f4e16438
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone50.0a1
first release with
nightly linux32
0e3f8401b804 / 50.0a1 / 20160627030215 / files
nightly linux64
0e3f8401b804 / 50.0a1 / 20160627030215 / files
nightly mac
0e3f8401b804 / 50.0a1 / 20160627030215 / files
nightly win32
0e3f8401b804 / 50.0a1 / 20160627030215 / files
nightly win64
0e3f8401b804 / 50.0a1 / 20160627030215 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
media/libjpeg/README
media/libjpeg/README-turbo.txt
testing/web-platform/meta/web-animations/interfaces/AnimationTimeline/idlharness.html.ini
testing/web-platform/tests/web-animations/interfaces/AnimationTimeline/document-timeline.html
testing/web-platform/tests/web-animations/interfaces/AnimationTimeline/idlharness.html
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -131,19 +131,19 @@
              value="&trackingProtectionPBMLearnMore.label;"/>
       <spacer flex="1" />
       <button id="changeBlockListPBM"
               label="&changeBlockList.label;" accesskey="&changeBlockList.accesskey;"
               preference="pref.privacy.disable_button.change_blocklist"/>
     </hbox>
   </vbox>
   <vbox>
-    <description>&doNotTrack.pre.label;<html:a
-    class="inline-link" id="doNotTrackSettings" href="#"
-    >&doNotTrack.settings.label;</html:a>&doNotTrack.post.label;</description>
+    <description>&doNotTrack.pre.label;<label
+    class="text-link" id="doNotTrackSettings" href="#"
+    >&doNotTrack.settings.label;</label>&doNotTrack.post.label;</description>
   </vbox>
 </groupbox>
 
 <!-- History -->
 <groupbox id="historyGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&history.label;</label></caption>
   <hbox align="center">
     <label id="historyModeLabel"
@@ -160,32 +160,32 @@
     <label>&historyHeader.post.label;</label>
   </hbox>
   <deck id="historyPane">
     <vbox id="historyRememberPane">
       <hbox align="center" flex="1">
         <vbox flex="1">
           <description>&rememberDescription.label;</description>
           <separator class="thin"/>
-          <description>&rememberActions.pre.label;<html:a
-          class="inline-link" id="historyRememberClear" href="#"
-          >&rememberActions.clearHistory.label;</html:a>&rememberActions.middle.label;<html:a
-          class="inline-link" id="historyRememberCookies" href="#"
-          >&rememberActions.removeCookies.label;</html:a>&rememberActions.post.label;</description>
+          <description>&rememberActions.pre.label;<label
+          class="text-link" id="historyRememberClear" href="#"
+          >&rememberActions.clearHistory.label;</label>&rememberActions.middle.label;<label
+          class="text-link" id="historyRememberCookies" href="#"
+          >&rememberActions.removeCookies.label;</label>&rememberActions.post.label;</description>
         </vbox>
       </hbox>
     </vbox>
     <vbox id="historyDontRememberPane">
       <hbox align="center" flex="1">
         <vbox flex="1">
           <description>&dontrememberDescription.label;</description>
           <separator class="thin"/>
-          <description>&dontrememberActions.pre.label;<html:a
-          class="inline-link" id="historyDontRememberClear" href="#"
-          >&dontrememberActions.clearHistory.label;</html:a>&dontrememberActions.post.label;</description>
+          <description>&dontrememberActions.pre.label;<label
+          class="text-link" id="historyDontRememberClear" href="#"
+          >&dontrememberActions.clearHistory.label;</label>&dontrememberActions.post.label;</description>
         </vbox>
       </hbox>
     </vbox>
     <vbox id="historyCustomPane">
       <separator class="thin"/>
       <vbox>
         <vbox align="start">
           <checkbox id="privateBrowsingAutoStart"
--- a/dom/animation/DocumentTimeline.cpp
+++ b/dom/animation/DocumentTimeline.cpp
@@ -31,16 +31,41 @@ NS_IMPL_ADDREF_INHERITED(DocumentTimelin
 NS_IMPL_RELEASE_INHERITED(DocumentTimeline, AnimationTimeline)
 
 JSObject*
 DocumentTimeline::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return DocumentTimelineBinding::Wrap(aCx, this, aGivenProto);
 }
 
+/* static */ already_AddRefed<DocumentTimeline>
+DocumentTimeline::Constructor(const GlobalObject& aGlobal,
+                              const DOMHighResTimeStamp& aOriginTime,
+                              ErrorResult& aRv)
+{
+  nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aGlobal.Context());
+  if (!doc) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  TimeDuration originTime = TimeDuration::FromMilliseconds(aOriginTime);
+  if (originTime == TimeDuration::Forever() ||
+      originTime == -TimeDuration::Forever()) {
+    nsAutoString inputOriginTime;
+    inputOriginTime.AppendFloat(aOriginTime);
+    aRv.ThrowTypeError<dom::MSG_TIME_VALUE_OUT_OF_RANGE>(
+      NS_LITERAL_STRING("Origin time"));
+    return nullptr;
+  }
+  RefPtr<DocumentTimeline> timeline = new DocumentTimeline(doc, originTime);
+
+  return timeline.forget();
+}
+
 Nullable<TimeDuration>
 DocumentTimeline::GetCurrentTime() const
 {
   return ToTimelineTime(GetCurrentTimeStamp());
 }
 
 TimeStamp
 DocumentTimeline::GetCurrentTimeStamp() const
@@ -83,17 +108,19 @@ DocumentTimeline::ToTimelineTime(const T
     return result;
   }
 
   RefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
   if (MOZ_UNLIKELY(!timing)) {
     return result;
   }
 
-  result.SetValue(aTimeStamp - timing->GetNavigationStartTimeStamp());
+  result.SetValue(aTimeStamp
+                  - timing->GetNavigationStartTimeStamp()
+                  - mOriginTime);
   return result;
 }
 
 void
 DocumentTimeline::NotifyAnimationUpdated(Animation& aAnimation)
 {
   AnimationTimeline::NotifyAnimationUpdated(aAnimation);
 
@@ -199,17 +226,17 @@ TimeStamp
 DocumentTimeline::ToTimeStamp(const TimeDuration& aTimeDuration) const
 {
   TimeStamp result;
   RefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
   if (MOZ_UNLIKELY(!timing)) {
     return result;
   }
 
-  result = timing->GetNavigationStartTimeStamp() + aTimeDuration;
+  result = timing->GetNavigationStartTimeStamp() + aTimeDuration + mOriginTime;
   return result;
 }
 
 nsRefreshDriver*
 DocumentTimeline::GetRefreshDriver() const
 {
   nsIPresShell* presShell = mDocument->GetShell();
   if (MOZ_UNLIKELY(!presShell)) {
--- a/dom/animation/DocumentTimeline.h
+++ b/dom/animation/DocumentTimeline.h
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_DocumentTimeline_h
 #define mozilla_dom_DocumentTimeline_h
 
 #include "mozilla/TimeStamp.h"
 #include "AnimationTimeline.h"
 #include "nsIDocument.h"
+#include "nsDOMNavigationTiming.h" // for DOMHighResTimeStamp
 #include "nsRefreshDriver.h"
 
 struct JSContext;
 
 // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
 // GetTickCount().
 #ifdef GetCurrentTime
 #undef GetCurrentTime
@@ -23,20 +24,21 @@ struct JSContext;
 namespace mozilla {
 namespace dom {
 
 class DocumentTimeline final
   : public AnimationTimeline
   , public nsARefreshObserver
 {
 public:
-  explicit DocumentTimeline(nsIDocument* aDocument)
+  DocumentTimeline(nsIDocument* aDocument, const TimeDuration& aOriginTime)
     : AnimationTimeline(aDocument->GetParentObject())
     , mDocument(aDocument)
     , mIsObservingRefreshDriver(false)
+    , mOriginTime(aOriginTime)
   {
   }
 
 protected:
   virtual ~DocumentTimeline()
   {
     MOZ_ASSERT(!mIsObservingRefreshDriver, "Timeline should have disassociated"
                " from the refresh driver before being destroyed");
@@ -45,16 +47,21 @@ protected:
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DocumentTimeline,
                                                          AnimationTimeline)
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
+  static already_AddRefed<DocumentTimeline>
+  Constructor(const GlobalObject& aGlobal,
+              const DOMHighResTimeStamp& aOriginTime,
+              ErrorResult& aRv);
+
   // AnimationTimeline methods
   virtual Nullable<TimeDuration> GetCurrentTime() const override;
 
   bool TracksWallclockTime() const override
   {
     nsRefreshDriver* refreshDriver = GetRefreshDriver();
     return !refreshDriver ||
            !refreshDriver->IsTestControllingRefreshesEnabled();
@@ -79,14 +86,16 @@ protected:
 
   nsCOMPtr<nsIDocument> mDocument;
 
   // The most recently used refresh driver time. This is used in cases where
   // we don't have a refresh driver (e.g. because we are in a display:none
   // iframe).
   mutable TimeStamp mLastRefreshDriverTime;
   bool mIsObservingRefreshDriver;
+
+  TimeDuration mOriginTime;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_DocumentTimeline_h
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -32,16 +32,17 @@ support-files =
   css-transitions/file_document-get-animations.html
   css-transitions/file_effect-target.html
   css-transitions/file_element-get-animations.html
   css-transitions/file_keyframeeffect-getkeyframes.html
   css-transitions/file_pseudoElement-get-animations.html
   document-timeline/file_document-timeline.html
   mozilla/file_deferred_start.html
   mozilla/file_disabled_properties.html
+  mozilla/file_document-timeline-origin-time-range.html
   mozilla/file_hide_and_show.html
   mozilla/file_partial_keyframes.html
   style/file_animation-seeking-with-current-time.html
   style/file_animation-seeking-with-start-time.html
   testcommon.js
 
 [css-animations/test_animations-dynamic-changes.html]
 [css-animations/test_animation-cancel.html]
@@ -77,13 +78,14 @@ skip-if = buildapp == 'mulet'
 [css-transitions/test_keyframeeffect-getkeyframes.html]
 [css-transitions/test_pseudoElement-get-animations.html]
 [document-timeline/test_document-timeline.html]
 [document-timeline/test_request_animation_frame.html]
 skip-if = buildapp == 'mulet'
 [mozilla/test_deferred_start.html]
 skip-if = (toolkit == 'gonk' && debug)
 [mozilla/test_disabled_properties.html]
+[mozilla/test_document-timeline-origin-time-range.html]
 [mozilla/test_hide_and_show.html]
 [mozilla/test_partial_keyframes.html]
 [style/test_animation-seeking-with-current-time.html]
 [style/test_animation-seeking-with-start-time.html]
 [sandbox/test_set-easing.html]
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/mozilla/file_document-timeline-origin-time-range.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="../testcommon.js"></script>
+<body>
+<script>
+'use strict';
+
+// If the originTime parameter passed to the DocumentTimeline exceeds
+// the range of the internal storage type (a signed 64-bit integer number
+// of ticks--a platform-dependent unit) then we should throw.
+// Infinity isn't allowed as an origin time value and clamping to just
+// inside the allowed range will just mean we overflow elsewhere.
+
+test(function(t) {
+  assert_throws({name: 'TypeError'},
+    function() { new DocumentTimeline(Number.MAX_SAFE_INTEGER); });
+}, 'Calculated current time is positive infinity');
+
+test(function(t) {
+  assert_throws({name: 'TypeError'},
+    function() { new DocumentTimeline(-1 * Number.MAX_SAFE_INTEGER); });
+}, 'Calculated current time is negative infinity');
+
+done();
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/mozilla/test_document-timeline-origin-time-range.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+'use strict';
+setup({explicit_done: true});
+SpecialPowers.pushPrefEnv(
+  { "set": [["dom.animations-api.core.enabled", true]]},
+  function() {
+    window.open("file_document-timeline-origin-time-range.html");
+  });
+</script>
--- a/dom/base/ScreenOrientation.cpp
+++ b/dom/base/ScreenOrientation.cpp
@@ -10,16 +10,17 @@
 #include "nsSandboxFlags.h"
 #include "nsScreen.h"
 
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/Hal.h"
 #include "mozilla/Preferences.h"
 
 #include "mozilla/dom/Promise.h"
+#include "nsContentUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(ScreenOrientation,
                                    DOMEventTargetHelper,
                                    mScreen);
 
@@ -404,40 +405,49 @@ ScreenOrientation::UnlockDeviceOrientati
   }
 
   mFullScreenListener = nullptr;
 }
 
 OrientationType
 ScreenOrientation::DeviceType() const
 {
-  return mType;
+  return ShouldResistFingerprinting() ? OrientationType::Landscape_primary
+                                      : mType;
 }
 
 uint16_t
 ScreenOrientation::DeviceAngle() const
 {
-  return mAngle;
+  return ShouldResistFingerprinting() ? 0 : mAngle;
 }
 
 OrientationType
 ScreenOrientation::GetType(ErrorResult& aRv) const
 {
+  if (ShouldResistFingerprinting()) {
+    return OrientationType::Landscape_primary;
+  }
+
   nsIDocument* doc = GetResponsibleDocument();
   if (!doc) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return OrientationType::Portrait_primary;
   }
 
   return doc->CurrentOrientationType();
 }
 
 uint16_t
 ScreenOrientation::GetAngle(ErrorResult& aRv) const
 {
+  if (ShouldResistFingerprinting()) {
+    return 0;
+  }
+
   nsIDocument* doc = GetResponsibleDocument();
   if (!doc) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return 0;
   }
 
   return doc->CurrentOrientationAngle();
 }
@@ -490,16 +500,20 @@ ScreenOrientation::GetResponsibleDocumen
   }
 
   return owner->GetDoc();
 }
 
 void
 ScreenOrientation::Notify(const hal::ScreenConfiguration& aConfiguration)
 {
+  if (ShouldResistFingerprinting()) {
+    return;
+  }
+
   nsIDocument* doc = GetResponsibleDocument();
   if (!doc) {
     return;
   }
 
   ScreenOrientationInternal orientation = aConfiguration.orientation();
   if (orientation != eScreenOrientation_PortraitPrimary &&
       orientation != eScreenOrientation_PortraitSecondary &&
@@ -566,16 +580,26 @@ ScreenOrientation::DispatchChangeEvent()
 }
 
 JSObject*
 ScreenOrientation::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return ScreenOrientationBinding::Wrap(aCx, this, aGivenProto);
 }
 
+bool
+ScreenOrientation::ShouldResistFingerprinting() const
+{
+  bool resist = false;
+  if (nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner()) {
+    resist = nsContentUtils::ShouldResistFingerprinting(owner->GetDocShell());
+  }
+  return resist;
+}
+
 NS_IMPL_ISUPPORTS(ScreenOrientation::VisibleEventListener, nsIDOMEventListener)
 
 NS_IMETHODIMP
 ScreenOrientation::VisibleEventListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   // Document may have become visible, if the page is visible, run the steps
   // following the "now visible algorithm" as specified.
   nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
--- a/dom/base/ScreenOrientation.h
+++ b/dom/base/ScreenOrientation.h
@@ -97,16 +97,18 @@ private:
   // a ScreenOrientationInternal argument instead of an OrientationType.
   // This method exists in order to share implementation with nsScreen that
   // uses ScreenOrientationInternal.
   already_AddRefed<Promise> LockInternal(ScreenOrientationInternal aOrientation,
                                          ErrorResult& aRv);
 
   void DispatchChangeEvent();
 
+  bool ShouldResistFingerprinting() const;
+
   LockPermission GetLockOrientationPermission(bool aCheckSandbox) const;
 
   // Gets the responsible document as defined in the spec.
   nsIDocument* GetResponsibleDocument() const;
 
   RefPtr<nsScreen> mScreen;
   RefPtr<FullScreenEventListener> mFullScreenListener;
   RefPtr<VisibleEventListener> mVisibleListener;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3236,17 +3236,17 @@ nsDocument::IsWebAnimationsEnabled(JSCon
   return nsContentUtils::IsCallerChrome() ||
          Preferences::GetBool("dom.animations-api.core.enabled");
 }
 
 DocumentTimeline*
 nsDocument::Timeline()
 {
   if (!mDocumentTimeline) {
-    mDocumentTimeline = new DocumentTimeline(this);
+    mDocumentTimeline = new DocumentTimeline(this, TimeDuration(0));
   }
 
   return mDocumentTimeline;
 }
 
 void
 nsDocument::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
 {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -13238,18 +13238,18 @@ nsGlobalWindow::DisableDeviceSensor(uint
   }
 }
 
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
 void
 nsGlobalWindow::EnableOrientationChangeListener()
 {
   MOZ_ASSERT(IsInnerWindow());
-
-  if (!mOrientationChangeObserver) {
+  if (!nsContentUtils::ShouldResistFingerprinting(mDocShell) &&
+      !mOrientationChangeObserver) {
     mOrientationChangeObserver =
       new WindowOrientationObserver(this);
   }
 }
 
 void
 nsGlobalWindow::DisableOrientationChangeListener()
 {
@@ -14082,17 +14082,18 @@ nsGlobalWindow::IsModalContentWindow(JSC
 {
   return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
 }
 
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
 int16_t
 nsGlobalWindow::Orientation() const
 {
-  return WindowOrientationObserver::OrientationAngle();
+  return nsContentUtils::ShouldResistFingerprinting(mDocShell) ?
+           0 : WindowOrientationObserver::OrientationAngle();
 }
 #endif
 
 Console*
 nsGlobalWindow::GetConsole(ErrorResult& aRv)
 {
   MOZ_RELEASE_ASSERT(IsInnerWindow());
 
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -1837,18 +1837,33 @@ ValidateCurrentNode(nsRange* aRange, Ran
   nsCOMPtr<nsINode> node = aIter.GetCurrentNode();
   if (!node) {
     // We don't have to worry that the node was removed if it doesn't exist,
     // e.g., the iterator is done.
     return true;
   }
 
   nsresult res = nsRange::CompareNodeToRange(node, aRange, &before, &after);
-
-  return NS_SUCCEEDED(res) && !before && !after;
+  NS_ENSURE_SUCCESS(res, false);
+
+  if (before || after) {
+    nsCOMPtr<nsIDOMCharacterData> charData = do_QueryInterface(node);
+    if (charData) {
+      // If we're dealing with the start/end container which is a character
+      // node, pretend that the node is in the range.
+      if (before && node == aRange->GetStartParent()) {
+        before = false;
+      }
+      if (after && node == aRange->GetEndParent()) {
+        after = false;
+      }
+    }
+  }
+
+  return !before && !after;
 }
 
 nsresult
 nsRange::CutContents(DocumentFragment** aFragment)
 {
   if (aFragment) {
     *aFragment = nullptr;
   }
--- a/dom/base/nsScreen.cpp
+++ b/dom/base/nsScreen.cpp
@@ -188,35 +188,31 @@ mozilla::dom::ScreenOrientation*
 nsScreen::Orientation() const
 {
   return mScreenOrientation;
 }
 
 void
 nsScreen::GetMozOrientation(nsString& aOrientation) const
 {
-  if (ShouldResistFingerprinting()) {
+  switch (mScreenOrientation->DeviceType()) {
+  case OrientationType::Portrait_primary:
+    aOrientation.AssignLiteral("portrait-primary");
+    break;
+  case OrientationType::Portrait_secondary:
+    aOrientation.AssignLiteral("portrait-secondary");
+    break;
+  case OrientationType::Landscape_primary:
     aOrientation.AssignLiteral("landscape-primary");
-  } else {
-    switch (mScreenOrientation->DeviceType()) {
-    case OrientationType::Portrait_primary:
-      aOrientation.AssignLiteral("portrait-primary");
-      break;
-    case OrientationType::Portrait_secondary:
-      aOrientation.AssignLiteral("portrait-secondary");
-      break;
-    case OrientationType::Landscape_primary:
-      aOrientation.AssignLiteral("landscape-primary");
-      break;
-    case OrientationType::Landscape_secondary:
-      aOrientation.AssignLiteral("landscape-secondary");
-      break;
-    default:
-      MOZ_CRASH("Unacceptable screen orientation type.");
-    }
+    break;
+  case OrientationType::Landscape_secondary:
+    aOrientation.AssignLiteral("landscape-secondary");
+    break;
+  default:
+    MOZ_CRASH("Unacceptable screen orientation type.");
   }
 }
 
 NS_IMETHODIMP
 nsScreen::GetSlowMozOrientation(nsAString& aOrientation)
 {
   nsString orientation;
   GetMozOrientation(orientation);
@@ -258,16 +254,19 @@ nsScreen::MozLockOrientation(const nsASt
   }
   return MozLockOrientation(orientations, aRv);
 }
 
 bool
 nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
                              ErrorResult& aRv)
 {
+  if (ShouldResistFingerprinting()) {
+    return false;
+  }
   ScreenOrientationInternal orientation = eScreenOrientation_None;
 
   for (uint32_t i = 0; i < aOrientations.Length(); ++i) {
     const nsString& item = aOrientations[i];
 
     if (item.EqualsLiteral("portrait")) {
       orientation |= eScreenOrientation_PortraitPrimary |
                      eScreenOrientation_PortraitSecondary;
@@ -305,16 +304,19 @@ nsScreen::MozLockOrientation(const Seque
   // This is only for compilers that don't understand that the previous switch
   // will always return.
   MOZ_CRASH("unexpected lock orientation permission value");
 }
 
 void
 nsScreen::MozUnlockOrientation()
 {
+  if (ShouldResistFingerprinting()) {
+    return;
+  }
   UpdateDocShellOrientationLock(GetOwner(), eScreenOrientation_None);
   mScreenOrientation->UnlockDeviceOrientation();
 }
 
 bool
 nsScreen::IsDeviceSizePageSize()
 {
   if (nsPIDOMWindowInner* owner = GetOwner()) {
--- a/dom/base/test/chrome/bug418986-1.js
+++ b/dom/base/test/chrome/bug418986-1.js
@@ -17,16 +17,18 @@ var test = function (isContent) {
     ["screen.availWidth", "innerWidth"],
     ["screen.availHeight", "innerHeight"],
     ["screen.left", 0],
     ["screen.top", 0],
     ["screen.availLeft", 0],
     ["screen.availTop", 0],
     ["screen.width", "innerWidth"],
     ["screen.height", "innerHeight"],
+    ["screen.orientation.type", "'landscape-primary'"],
+    ["screen.orientation.angle", 0],
     ["screen.mozOrientation", "'landscape-primary'"],
     ["devicePixelRatio", 1]
   ];
 
   // checkPair: tests if members of pair [a, b] are equal when evaluated.
   let checkPair = function (a, b) {
     is(eval(a), eval(b), a + " should be equal to " + b);
   };
new file mode 100644
--- /dev/null
+++ b/dom/base/test/file_bug1274806.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8" /> 
+  <title></title>
+  <script>
+  window.onload = function() {
+    setTimeout(function() {
+      var rng = document.createRange();
+      rng.setStart(document.getElementsByTagName("p").item(0).firstChild, 100);
+      rng.setEndAfter(document.getElementsByTagName("p").item(0));
+      try {
+        rng.extractContents();
+        opener.ok(true, "extractContents should not throw when document in iframe is being modified.");
+      } catch(ex) {
+        opener.ok(false, "extractContents shouldn't have thrown: " + ex);
+      }
+
+      opener.setTimeout("SimpleTest.finish();", 0);
+      window.close();
+
+    }, 0);
+  };
+  </script>
+</head>
+<body>
+<p>
+  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur elit nisi, convallis sed scelerisque sit amet, vestibulum eu odio. Pellentesque et quam et nibh sollicitudin rutrum. Fusce tristique hendrerit ligula, et euismod sapien facilisis quis. Donec tincidunt turpis tortor, in pharetra tellus euismod ac. Vestibulum consectetur nulla lacinia, consectetur mauris ac, tempus libero. Nam non dui id enim dapibus porta id sed lectus. Praesent at suscipit neque. Vestibulum tellus lorem, placerat et volutpat sed, elementum eget lacus. Sed interdum nisi et imperdiet varius. Sed non magna odio. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus velit risus, accumsan nec efficitur nec, semper sed arcu. Praesent consectetur lectus justo, fringilla imperdiet neque lobortis id. Donec efficitur pulvinar finibus.
+  <iframe src="data:text/html,<script>window.onunload = function() {document.removeChild(document.documentElement); }</script>" width="10" height="10"></iframe>
+</p>
+<p>test</p>
+</body>
+</html>
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -155,16 +155,17 @@ support-files =
   file_bug869432.eventsource
   file_bug869432.eventsource^headers^
   file_bug902350.html
   file_bug902350_frame.html
   file_bug907892.html
   file_bug945152.jar
   file_bug1263696_frame_pass.html
   file_bug1263696_frame_fail.html
+  file_bug1274806.html
   file_general_document.html
   file_html_in_xhr.html
   file_html_in_xhr.sjs
   file_html_in_xhr2.html
   file_html_in_xhr3.html
   file_htmlserializer_1.html
   file_htmlserializer_1_bodyonly.html
   file_htmlserializer_1_format.html
@@ -659,16 +660,17 @@ skip-if = buildapp == 'b2g'
 [test_bug1163743.html]
 [test_bug1165501.html]
 [test_bug1187157.html]
 [test_bug1198095.html]
 [test_bug1238440.html]
 [test_bug1250148.html]
 [test_bug1259588.html]
 [test_bug1263696.html]
+[test_bug1274806.html]
 [test_caretPositionFromPoint.html]
 [test_change_policy.html]
 skip-if = buildapp == 'b2g' #no ssl support
 [test_classList.html]
 [test_clearTimeoutIntervalNoArg.html]
 [test_constructor-assignment.html]
 [test_constructor.html]
 [test_copyimage.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_bug1274806.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1274806
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1274806</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  SimpleTest.waitForExplicitFinish();
+
+  /** Test for Bug 1274806 **/
+  function test() {
+    window.testWindow = window.open("file_bug1274806.html", "", "");
+  };
+
+  </script>
+</head>
+<body onload="setTimeout(test, 0);">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1274806">Mozilla Bug 1274806</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -93,9 +93,10 @@ MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TY
 MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a typed array on SharedArrayBuffer")
 MSG_DEF(MSG_CACHE_ADD_FAILED_RESPONSE, 3, JSEXN_TYPEERR, "Cache got {0} response with bad status {1} while trying to add request {2}")
 MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 2, JSEXN_TYPEERR, "Failed to update the ServiceWorker for scope {0] because the registration has been {1} since the update was scheduled.")
 MSG_DEF(MSG_INVALID_DURATION_ERROR, 1, JSEXN_TYPEERR, "Invalid duration '{0}'.")
 MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.")
 MSG_DEF(MSG_USELESS_SETTIMEOUT, 1, JSEXN_TYPEERR, "Useless {0} call (missing quotes around argument?)")
 MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")
 MSG_DEF(MSG_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache file stream that has already been closed.")
+MSG_DEF(MSG_TIME_VALUE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "{0} is outside the supported range for time values.")
 MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -786,20 +786,21 @@ WMFVideoMFTManager::Output(int64_t aStre
           LOG("Excessive Video MFTDecoder returning success but no output; giving up");
           mGotExcessiveNullOutput = true;
           return E_FAIL;
         }
         continue;
       }
       if (mSeekTargetThreshold.isSome()) {
         media::TimeUnit pts = GetSampleTime(sample);
-        if (!pts.IsValid()) {
+		media::TimeUnit duration = GetSampleDuration(sample);
+        if (!pts.IsValid() || !duration.IsValid()) {
           return E_FAIL;
         }
-        if (pts < mSeekTargetThreshold.ref()) {
+        if ((pts + duration) < mSeekTargetThreshold.ref()) {
           LOG("Dropping video frame which pts is smaller than seek target.");
           // It is necessary to clear the pointer to release the previous output
           // buffer.
           sample = nullptr;
           continue;
         }
         mSeekTargetThreshold.reset();
       }
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -158,25 +158,25 @@ CSP_ContentTypeToDirective(nsContentPoli
       return nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE;
 
     case nsIContentPolicy::TYPE_SUBDOCUMENT:
       return nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE;
 
     case nsIContentPolicy::TYPE_WEBSOCKET:
     case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
     case nsIContentPolicy::TYPE_BEACON:
+    case nsIContentPolicy::TYPE_PING:
     case nsIContentPolicy::TYPE_FETCH:
       return nsIContentSecurityPolicy::CONNECT_SRC_DIRECTIVE;
 
     case nsIContentPolicy::TYPE_OBJECT:
     case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
       return nsIContentSecurityPolicy::OBJECT_SRC_DIRECTIVE;
 
     case nsIContentPolicy::TYPE_XBL:
-    case nsIContentPolicy::TYPE_PING:
     case nsIContentPolicy::TYPE_DTD:
     case nsIContentPolicy::TYPE_OTHER:
       return nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE;
 
     // csp shold not block top level loads, e.g. in case
     // of a redirect.
     case nsIContentPolicy::TYPE_DOCUMENT:
     // CSP can not block csp reports
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_ping.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1100181 - CSP: Enforce connect-src when submitting pings</title>
+</head>
+<body>
+  <!-- we are using an image for the test, but can be anything -->
+  <a id="testlink"
+     href="http://mochi.test:8888/tests/image/test/mochitest/blue.png"
+     ping="http://mochi.test:8888/tests/image/test/mochitest/blue.png?send-ping">
+     Send ping
+  </a>
+  
+  <script type="text/javascript">
+    var link = document.getElementById("testlink");
+    link.click();
+  </script>
+</body>
+</html>
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -157,16 +157,17 @@ support-files =
   file_fontloader.sjs
   file_fontloader.woff
   file_block_all_mcb.sjs
   file_block_all_mixed_content_frame_navigation1.html
   file_block_all_mixed_content_frame_navigation2.html
   file_form_action_server.sjs
   !/image/test/mochitest/blue.png
   file_meta_whitespace_skipping.html
+  file_ping.html
 
 [test_base-uri.html]
 [test_blob_data_schemes.html]
 [test_connect-src.html]
 [test_CSP.html]
 [test_allow_https_schemes.html]
 skip-if = buildapp == 'b2g' #no ssl support
 [test_bug663567.html]
@@ -243,8 +244,9 @@ skip-if = toolkit == 'android' #investig
 [test_multipartchannel.html]
 [test_fontloader.html]
 [test_block_all_mixed_content.html]
 tags = mcb
 [test_block_all_mixed_content_frame_navigation.html]
 tags = mcb
 [test_form_action_blocks_url.html]
 [test_meta_whitespace_skipping.html]
+[test_ping.html]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/test_ping.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1100181 - CSP: Enforce connect-src when submitting pings</title>
+  <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe style="width:100%;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+/*
+ * Description of the test:
+ *   We load a page with a given CSP and verify that hyperlink auditing
+ *   is correctly evaluated through the "connect-src" directive.
+ */
+
+// Need to pref hyperlink auditing on since it's disabled by default.
+SpecialPowers.setBoolPref("browser.send_pings", true);
+
+SimpleTest.waitForExplicitFinish();
+
+var tests = [
+  {
+    result : "allowed",
+    policy : "connect-src 'self'"
+  },
+  {
+    result : "blocked",
+    policy : "connect-src 'none'"
+  }
+];
+
+// initializing to -1 so we start at index 0 when we start the test
+var counter = -1;
+
+function checkResult(aResult) {
+  is(aResult, tests[counter].result, "should be " + tests[counter].result + " in test " + counter + "!");
+  loadNextTest();
+}
+
+// We use the examiner to identify requests that hit the wire and requests
+// that are blocked by CSP and bubble up the result to the including iframe
+// document (parent).
+function examiner() {
+  SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
+}
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+   if (topic === "specialpowers-http-notify-request") {
+      // making sure we do not bubble a result for something
+      // other then the request in question.
+      if (!data.includes("send-ping")) {
+        return;
+      }
+      checkResult("allowed");
+      return;
+    }
+
+    if (topic === "csp-on-violate-policy") {
+      // making sure we do not bubble a result for something
+      // other then the request in question.
+      var asciiSpec = SpecialPowers.getPrivilegedProps(
+        SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
+      if (!asciiSpec.includes("send-ping")) {
+        return;
+      }
+      checkResult("blocked");
+    }
+  },
+  remove: function() {
+    SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
+  }
+}
+window.ConnectSrcExaminer = new examiner();
+
+function loadNextTest() {
+  counter++;
+  if (counter == tests.length) {
+    window.ConnectSrcExaminer.remove();
+    SimpleTest.finish();
+    return;
+  }
+
+  var src = "file_testserver.sjs";
+  // append the file that should be served
+  src += "?file=" + escape("tests/dom/security/test/csp/file_ping.html");
+  // append the CSP that should be used to serve the file
+  src += "&csp=" + escape(tests[counter].policy);
+
+  document.getElementById("testframe").src = src;
+}
+
+// start running the tests
+loadNextTest();
+
+</script>
+</body>
+</html>
--- a/dom/webidl/DocumentTimeline.webidl
+++ b/dom/webidl/DocumentTimeline.webidl
@@ -5,13 +5,12 @@
  *
  * The origin of this IDL file is
  * https://w3c.github.io/web-animations/#documenttimeline
  *
  * Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-// Not yet implemented:
-// [Constructor (DOMHighResTimeStamp originTime)]
-[Func="nsDocument::IsWebAnimationsEnabled"]
+[Func="nsDocument::IsWebAnimationsEnabled",
+ Constructor (DOMHighResTimeStamp originTime)]
 interface DocumentTimeline : AnimationTimeline {
 };
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -847,9 +847,16 @@ gfxPlatformGtk::CreateHardwareVsyncSourc
       return gfxPlatform::CreateHardwareVsyncSource();
     }
     return vsyncSource.forget();
   }
   NS_WARNING("SGI_video_sync unsupported. Falling back to software vsync.");
   return gfxPlatform::CreateHardwareVsyncSource();
 }
 
+bool
+gfxPlatformGtk::SupportsApzTouchInput() const
+{
+  int value = gfxPrefs::TouchEventsEnabled();
+  return value == 1 || value == 2;
+}
+
 #endif
--- a/gfx/thebes/gfxPlatformGtk.h
+++ b/gfx/thebes/gfxPlatformGtk.h
@@ -118,16 +118,18 @@ public:
     bool UseImageOffscreenSurfaces();
 
     virtual gfxImageFormat GetOffscreenFormat() override;
 
     bool SupportsApzWheelInput() const override {
       return true;
     }
 
+    bool SupportsApzTouchInput() const override;
+
     void FontsPrefsChanged(const char *aPref) override;
 
     // maximum number of fonts to substitute for a generic
     uint32_t MaxGenericSubstitions();
 
     bool SupportsPluginDirectBitmapDrawing() override {
       return true;
     }
--- a/image/Decoder.cpp
+++ b/image/Decoder.cpp
@@ -424,27 +424,29 @@ Decoder::PostIsAnimated(int32_t aFirstFr
 }
 
 void
 Decoder::PostFrameStop(Opacity aFrameOpacity
                          /* = Opacity::SOME_TRANSPARENCY */,
                        DisposalMethod aDisposalMethod
                          /* = DisposalMethod::KEEP */,
                        int32_t aTimeout         /* = 0 */,
-                       BlendMethod aBlendMethod /* = BlendMethod::OVER */)
+                       BlendMethod aBlendMethod /* = BlendMethod::OVER */,
+                       const Maybe<nsIntRect>& aBlendRect /* = Nothing() */)
 {
   // We should be mid-frame
   MOZ_ASSERT(!IsMetadataDecode(), "Stopping frame during metadata decode");
   MOZ_ASSERT(mInFrame, "Stopping frame when we didn't start one");
   MOZ_ASSERT(mCurrentFrame, "Stopping frame when we don't have one");
 
   // Update our state
   mInFrame = false;
 
-  mCurrentFrame->Finish(aFrameOpacity, aDisposalMethod, aTimeout, aBlendMethod);
+  mCurrentFrame->Finish(aFrameOpacity, aDisposalMethod, aTimeout,
+                        aBlendMethod, aBlendRect);
 
   mProgress |= FLAG_FRAME_COMPLETE;
 
   // If we're not sending partial invalidations, then we send an invalidation
   // here when the first frame is complete.
   if (!ShouldSendPartialInvalidations() && mFrameCount == 1) {
     mInvalidRect.UnionRect(mInvalidRect,
                            gfx::IntRect(gfx::IntPoint(0, 0), GetSize()));
--- a/image/Decoder.h
+++ b/image/Decoder.h
@@ -327,17 +327,18 @@ protected:
   // Called by decoders when they end a frame. Informs the image, sends
   // notifications, and does internal book-keeping.
   // Specify whether this frame is opaque as an optimization.
   // For animated images, specify the disposal, blend method and timeout for
   // this frame.
   void PostFrameStop(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY,
                      DisposalMethod aDisposalMethod = DisposalMethod::KEEP,
                      int32_t aTimeout = 0,
-                     BlendMethod aBlendMethod = BlendMethod::OVER);
+                     BlendMethod aBlendMethod = BlendMethod::OVER,
+                     const Maybe<nsIntRect>& aBlendRect = Nothing());
 
   /**
    * Called by the decoders when they have a region to invalidate. We may not
    * actually pass these invalidations on right away.
    *
    * @param aRect The invalidation rect in the coordinate system of the unscaled
    *              image (that is, the image at its intrinsic size).
    * @param aRectAtTargetSize If not Nothing(), the invalidation rect in the
--- a/image/FrameAnimator.cpp
+++ b/image/FrameAnimator.cpp
@@ -620,17 +620,18 @@ FrameAnimator::DoBlend(nsIntRect* aDirty
                            compositingFrameData.mRect);
               }
             }
             DrawFrameTo(prevFrameData.mRawData, prevFrameData.mRect,
                         prevFrameData.mPaletteDataLength,
                         prevFrameData.mHasAlpha,
                         compositingFrameData.mRawData,
                         compositingFrameData.mRect,
-                        prevFrameData.mBlendMethod);
+                        prevFrameData.mBlendMethod,
+                        prevFrameData.mBlendRect);
           }
         }
     }
   } else if (needToBlankComposite) {
     // If we just created the composite, it could have anything in its
     // buffers. Clear them
     ClearFrame(compositingFrameData.mRawData,
                compositingFrameData.mRect);
@@ -668,17 +669,18 @@ FrameAnimator::DoBlend(nsIntRect* aDirty
   }
 
   // blit next frame into it's correct spot
   DrawFrameTo(nextFrameData.mRawData, nextFrameData.mRect,
               nextFrameData.mPaletteDataLength,
               nextFrameData.mHasAlpha,
               compositingFrameData.mRawData,
               compositingFrameData.mRect,
-              nextFrameData.mBlendMethod);
+              nextFrameData.mBlendMethod,
+              nextFrameData.mBlendRect);
 
   // Tell the image that it is fully 'downloaded'.
   mCompositingFrame->Finish();
 
   mLastCompositedFrameIndex = int32_t(aNextFrameIndex);
 
   return true;
 }
@@ -737,17 +739,17 @@ FrameAnimator::CopyFrameImage(const uint
 
   return true;
 }
 
 nsresult
 FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const nsIntRect& aSrcRect,
                            uint32_t aSrcPaletteLength, bool aSrcHasAlpha,
                            uint8_t* aDstPixels, const nsIntRect& aDstRect,
-                           BlendMethod aBlendMethod)
+                           BlendMethod aBlendMethod, const Maybe<nsIntRect>& aBlendRect)
 {
   NS_ENSURE_ARG_POINTER(aSrcData);
   NS_ENSURE_ARG_POINTER(aDstPixels);
 
   // According to both AGIF and APNG specs, offsets are unsigned
   if (aSrcRect.x < 0 || aSrcRect.y < 0) {
     NS_WARNING("FrameAnimator::DrawFrameTo: negative offsets not allowed");
     return NS_ERROR_FAILURE;
@@ -817,26 +819,63 @@ FrameAnimator::DrawFrameTo(const uint8_t
                                aDstRect.height,
                                reinterpret_cast<uint32_t*>(aDstPixels),
                                aDstRect.width * 4);
     if (!dst) {
       pixman_image_unref(src);
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
+    // XXX(seth): This is inefficient but we'll remove it quite soon when we
+    // move frame compositing into SurfacePipe. For now we need this because
+    // RemoveFrameRectFilter has transformed PNG frames with frame rects into
+    // imgFrame's with no frame rects, but with a region of 0 alpha where the
+    // frame rect should be. This works really nicely if we're using
+    // BlendMethod::OVER, but BlendMethod::SOURCE will result in that frame rect
+    // area overwriting the previous frame, which makes the animation look
+    // wrong. This quick hack fixes that by first compositing the whle new frame
+    // with BlendMethod::OVER, and then recopying the area that uses
+    // BlendMethod::SOURCE if needed. To make this work, the decoder has to
+    // provide a "blend rect" that tells us where to do this. This is just the
+    // frame rect, but hidden in a way that makes it invisible to most of the
+    // system, so we can keep eliminating dependencies on it.
     auto op = aBlendMethod == BlendMethod::SOURCE ? PIXMAN_OP_SRC
                                                   : PIXMAN_OP_OVER;
-    pixman_image_composite32(op,
-                             src,
-                             nullptr,
-                             dst,
-                             0, 0,
-                             0, 0,
-                             aSrcRect.x, aSrcRect.y,
-                             aSrcRect.width, aSrcRect.height);
+
+    if (aBlendMethod == BlendMethod::OVER || !aBlendRect ||
+        (aBlendMethod == BlendMethod::SOURCE && aSrcRect.IsEqualEdges(*aBlendRect))) {
+      // We don't need to do anything clever. (Or, in the case where no blend
+      // rect was specified, we can't.)
+      pixman_image_composite32(op,
+                               src,
+                               nullptr,
+                               dst,
+                               0, 0,
+                               0, 0,
+                               aSrcRect.x, aSrcRect.y,
+                               aSrcRect.width, aSrcRect.height);
+    } else {
+      // We need to do the OVER followed by SOURCE trick above.
+      pixman_image_composite32(PIXMAN_OP_OVER,
+                               src,
+                               nullptr,
+                               dst,
+                               0, 0,
+                               0, 0,
+                               aSrcRect.x, aSrcRect.y,
+                               aSrcRect.width, aSrcRect.height);
+      pixman_image_composite32(PIXMAN_OP_SRC,
+                               src,
+                               nullptr,
+                               dst,
+                               aBlendRect->x, aBlendRect->y,
+                               0, 0,
+                               aBlendRect->x, aBlendRect->y,
+                               aBlendRect->width, aBlendRect->height);
+    }
 
     pixman_image_unref(src);
     pixman_image_unref(dst);
   }
 
   return NS_OK;
 }
 
--- a/image/FrameAnimator.h
+++ b/image/FrameAnimator.h
@@ -2,16 +2,17 @@
  *
  * 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/. */
 
 #ifndef mozilla_image_FrameAnimator_h
 #define mozilla_image_FrameAnimator_h
 
+#include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/TimeStamp.h"
 #include "gfx2DGlue.h"
 #include "gfxTypes.h"
 #include "imgFrame.h"
 #include "nsCOMPtr.h"
 #include "nsRect.h"
 #include "SurfaceCache.h"
@@ -241,17 +242,18 @@ private: // methods
    * @aDstRect the size of the composition frame
    * @aBlendMethod the blend method for how to blend src on the composition
    * frame.
    */
   static nsresult DrawFrameTo(const uint8_t* aSrcData,
                               const nsIntRect& aSrcRect,
                               uint32_t aSrcPaletteLength, bool aSrcHasAlpha,
                               uint8_t* aDstPixels, const nsIntRect& aDstRect,
-                              BlendMethod aBlendMethod);
+                              BlendMethod aBlendMethod,
+                              const Maybe<nsIntRect>& aBlendRect);
 
 private: // data
   //! A weak pointer to our owning image.
   RasterImage* mImage;
 
   //! The intrinsic size of the image.
   gfx::IntSize mSize;
 
--- a/image/ShutdownTracker.cpp
+++ b/image/ShutdownTracker.cpp
@@ -27,23 +27,23 @@ static bool sShutdownHasStarted = false;
 ///////////////////////////////////////////////////////////////////////////////
 
 struct ShutdownObserver : public nsIObserver
 {
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD Observe(nsISupports*, const char* aTopic, const char16_t*) override
   {
-    if (strcmp(aTopic, "xpcom-shutdown") != 0) {
+    if (strcmp(aTopic, "xpcom-will-shutdown") != 0) {
       return NS_OK;
     }
 
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
     if (os) {
-      os->RemoveObserver(this, "xpcom-shutdown");
+      os->RemoveObserver(this, "xpcom-will-shutdown");
     }
 
     sShutdownHasStarted = true;
     return NS_OK;
   }
 
 private:
   virtual ~ShutdownObserver() { }
@@ -56,17 +56,17 @@ NS_IMPL_ISUPPORTS(ShutdownObserver, nsIO
 // Public API
 ///////////////////////////////////////////////////////////////////////////////
 
 /* static */ void
 ShutdownTracker::Initialize()
 {
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
-    os->AddObserver(new ShutdownObserver, "xpcom-shutdown", false);
+    os->AddObserver(new ShutdownObserver, "xpcom-will-shutdown", false);
   }
 }
 
 /* static */ bool
 ShutdownTracker::ShutdownHasStarted()
 {
   return sShutdownHasStarted;
 }
--- a/image/ShutdownTracker.h
+++ b/image/ShutdownTracker.h
@@ -12,18 +12,18 @@
 #define mozilla_image_ShutdownTracker_h
 
 namespace mozilla {
 namespace image {
 
 /**
  * ShutdownTracker is an imagelib-global service that allows callers to check
  * whether shutdown has started. It exists to avoid the need for registering
- * many 'xpcom-shutdown' notification observers on short-lived objects, which
- * would have an unnecessary performance cost.
+ * many 'xpcom-will-shutdown' notification observers on short-lived objects,
+ * which would have an unnecessary performance cost.
  */
 struct ShutdownTracker
 {
   /**
    * Initialize static data. Called during imagelib module initialization.
    */
   static void Initialize();
 
--- a/image/SurfaceFilters.h
+++ b/image/SurfaceFilters.h
@@ -7,16 +7,17 @@
 /**
  * This header contains various SurfaceFilter implementations that apply
  * transformations to image data, for usage with SurfacePipe.
  */
 
 #ifndef mozilla_image_SurfaceFilters_h
 #define mozilla_image_SurfaceFilters_h
 
+#include <algorithm>
 #include <stdint.h>
 #include <string.h>
 
 #include "mozilla/Likely.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/gfx/2D.h"
 
@@ -525,12 +526,368 @@ private:
   gfx::IntRect mUnclampedFrameRect;  /// The frame rect before clamping.
   UniquePtr<uint8_t[]> mBuffer;      /// The intermediate buffer, if one is
                                      /// necessary because the frame rect width
                                      /// is larger than the image's logical width.
   int32_t  mRow;                     /// The row in unclamped frame rect space
                                      /// that we're currently writing.
 };
 
+
+//////////////////////////////////////////////////////////////////////////////
+// ADAM7InterpolatingFilter
+//////////////////////////////////////////////////////////////////////////////
+
+template <typename Next> class ADAM7InterpolatingFilter;
+
+/**
+ * A configuration struct for ADAM7InterpolatingFilter.
+ */
+struct ADAM7InterpolatingConfig
+{
+  template <typename Next> using Filter = ADAM7InterpolatingFilter<Next>;
+};
+
+/**
+ * ADAM7InterpolatingFilter performs bilinear interpolation over an ADAM7
+ * interlaced image.
+ *
+ * ADAM7 breaks up the image into 8x8 blocks. On each of the 7 passes, a new set
+ * of pixels in each block receives their final values, according to the
+ * following pattern:
+ *
+ *    1 6 4 6 2 6 4 6
+ *    7 7 7 7 7 7 7 7
+ *    5 6 5 6 5 6 5 6
+ *    7 7 7 7 7 7 7 7
+ *    3 6 4 6 3 6 4 6
+ *    7 7 7 7 7 7 7 7
+ *    5 6 5 6 5 6 5 6
+ *    7 7 7 7 7 7 7 7
+ *
+ * When rendering the pixels that have not yet received their final values, we
+ * can get much better intermediate results if we interpolate between
+ * the pixels we *have* gotten so far. This filter performs bilinear
+ * interpolation by first performing linear interpolation horizontally for each
+ * "important" row (which we'll define as a row that has received any pixels
+ * with final values at all) and then performing linear interpolation vertically
+ * to produce pixel values for rows which aren't important on the current pass.
+ *
+ * Note that this filter totally ignores the data which is written to rows which
+ * aren't important on the current pass! It's fine to write nothing at all for
+ * these rows, although doing so won't cause any harm.
+ *
+ * XXX(seth): In bug 1280552 we'll add a SIMD implementation for this filter.
+ *
+ * The 'Next' template parameter specifies the next filter in the chain.
+ */
+template <typename Next>
+class ADAM7InterpolatingFilter final : public SurfaceFilter
+{
+public:
+  ADAM7InterpolatingFilter()
+    : mPass(0)  // The current pass, in the range 1..7. Starts at 0 so that
+                // DoResetToFirstRow() doesn't have to special case the first pass.
+    , mRow(0)
+  { }
+
+  template <typename... Rest>
+  nsresult Configure(const ADAM7InterpolatingConfig& aConfig, Rest... aRest)
+  {
+    nsresult rv = mNext.Configure(aRest...);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    if (mNext.IsValidPalettedPipe()) {
+      NS_WARNING("ADAM7InterpolatingFilter used with paletted pipe?");
+      return NS_ERROR_INVALID_ARG;
+    }
+
+    // We have two intermediate buffers, one for the previous row with final
+    // pixel values and one for the row that the previous filter in the chain is
+    // currently writing to.
+    size_t inputWidthInBytes = mNext.InputSize().width * sizeof(uint32_t);
+    mPreviousRow.reset(new (fallible) uint8_t[inputWidthInBytes]);
+    if (MOZ_UNLIKELY(!mPreviousRow)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    mCurrentRow.reset(new (fallible) uint8_t[inputWidthInBytes]);
+    if (MOZ_UNLIKELY(!mCurrentRow)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    memset(mPreviousRow.get(), 0, inputWidthInBytes);
+    memset(mCurrentRow.get(), 0, inputWidthInBytes);
+
+    ConfigureFilter(mNext.InputSize(), sizeof(uint32_t));
+    return NS_OK;
+  }
+
+  Maybe<SurfaceInvalidRect> TakeInvalidRect() override
+  {
+    return mNext.TakeInvalidRect();
+  }
+
+protected:
+  uint8_t* DoResetToFirstRow() override
+  {
+    mRow = 0;
+    mPass = std::min(mPass + 1, 7);
+
+    uint8_t* rowPtr = mNext.ResetToFirstRow();
+    if (mPass == 7) {
+      // Short circuit this filter on the final pass, since all pixels have
+      // their final values at that point.
+      return rowPtr;
+    }
+
+    return mCurrentRow.get();
+  }
+
+  uint8_t* DoAdvanceRow() override
+  {
+    MOZ_ASSERT(0 < mPass && mPass <= 7, "Invalid pass");
+
+    int32_t currentRow = mRow;
+    ++mRow;
+
+    if (mPass == 7) {
+      // On the final pass we short circuit this filter totally.
+      return mNext.AdvanceRow();
+    }
+
+    const int32_t lastImportantRow = LastImportantRow(InputSize().height, mPass);
+    if (currentRow > lastImportantRow) {
+      return nullptr;  // This pass is already complete.
+    }
+
+    if (!IsImportantRow(currentRow, mPass)) {
+      // We just ignore whatever the caller gives us for these rows. We'll
+      // interpolate them in later.
+      return mCurrentRow.get();
+    }
+
+    // This is an important row. We need to perform horizontal interpolation for
+    // these rows.
+    InterpolateHorizontally(mCurrentRow.get(), InputSize().width, mPass);
+
+    // Interpolate vertically between the previous important row and the current
+    // important row. We skip this if the current row is 0 (which is always an
+    // important row), because in that case there is no previous important row
+    // to interpolate with.
+    if (currentRow != 0) {
+      InterpolateVertically(mPreviousRow.get(), mCurrentRow.get(), mPass, mNext);
+    }
+
+    // Write out the current row itself, which, being an important row, does not
+    // need vertical interpolation.
+    uint32_t* currentRowAsPixels = reinterpret_cast<uint32_t*>(mCurrentRow.get());
+    mNext.WriteBuffer(currentRowAsPixels);
+
+    if (currentRow == lastImportantRow) {
+      // This is the last important row, which completes this pass. Note that
+      // for very small images, this may be the first row! Since there won't be
+      // another important row, there's nothing to interpolate with vertically,
+      // so we just duplicate this row until the end of the image.
+      while (mNext.WriteBuffer(currentRowAsPixels) == WriteState::NEED_MORE_DATA) { }
+
+      // All of the remaining rows in the image were determined above, so we're done.
+      return nullptr;
+    }
+
+    // The current row is now the previous important row; save it.
+    Swap(mPreviousRow, mCurrentRow);
+
+    MOZ_ASSERT(mRow < InputSize().height, "Reached the end of the surface without "
+                                          "hitting the last important row?");
+
+    return mCurrentRow.get();
+  }
+
+private:
+  static void InterpolateVertically(uint8_t* aPreviousRow,
+                                    uint8_t* aCurrentRow,
+                                    uint8_t aPass,
+                                    SurfaceFilter& aNext)
+  {
+    const float* weights = InterpolationWeights(ImportantRowStride(aPass));
+
+    // We need to interpolate vertically to generate the rows between the
+    // previous important row and the next one. Recall that important rows are
+    // rows which contain at least some final pixels; see
+    // InterpolateHorizontally() for some additional explanation as to what that
+    // means. Note that we've already written out the previous important row, so
+    // we start the iteration at 1.
+    for (int32_t outRow = 1; outRow < ImportantRowStride(aPass); ++outRow) {
+      const float weight = weights[outRow];
+
+      // We iterate through the previous and current important row every time we
+      // write out an interpolated row, so we need to copy the pointers.
+      uint8_t* prevRowBytes = aPreviousRow;
+      uint8_t* currRowBytes = aCurrentRow;
+
+      // Write out the interpolated pixels. Interpolation is componentwise.
+      aNext.template WritePixelsToRow<uint32_t>([&]{
+        uint32_t pixel = 0;
+        auto* component = reinterpret_cast<uint8_t*>(&pixel);
+        *component++ = InterpolateByte(*prevRowBytes++, *currRowBytes++, weight);
+        *component++ = InterpolateByte(*prevRowBytes++, *currRowBytes++, weight);
+        *component++ = InterpolateByte(*prevRowBytes++, *currRowBytes++, weight);
+        *component++ = InterpolateByte(*prevRowBytes++, *currRowBytes++, weight);
+        return AsVariant(pixel);
+      });
+    }
+  }
+
+  static void InterpolateHorizontally(uint8_t* aRow, int32_t aWidth, uint8_t aPass)
+  {
+    // Collect the data we'll need to perform horizontal interpolation. The
+    // terminology here bears some explanation: a "final pixel" is a pixel which
+    // has received its final value. On each pass, a new set of pixels receives
+    // their final value; see the diagram above of the 8x8 pattern that ADAM7
+    // uses. Any pixel which hasn't received its final value on this pass
+    // derives its value from either horizontal or vertical interpolation
+    // instead.
+    const size_t finalPixelStride = FinalPixelStride(aPass);
+    const size_t finalPixelStrideBytes = finalPixelStride * sizeof(uint32_t);
+    const size_t lastFinalPixel = LastFinalPixel(aWidth, aPass);
+    const size_t lastFinalPixelBytes = lastFinalPixel * sizeof(uint32_t);
+    const float* weights = InterpolationWeights(finalPixelStride);
+
+    // Interpolate blocks of pixels which lie between two final pixels.
+    // Horizontal interpolation is done in place, as we'll need the results
+    // later when we vertically interpolate.
+    for (size_t blockBytes = 0;
+         blockBytes < lastFinalPixelBytes;
+         blockBytes += finalPixelStrideBytes) {
+      uint8_t* finalPixelA = aRow + blockBytes;
+      uint8_t* finalPixelB = aRow + blockBytes + finalPixelStrideBytes;
+
+      MOZ_ASSERT(finalPixelA < aRow + aWidth * sizeof(uint32_t),
+                 "Running off end of buffer");
+      MOZ_ASSERT(finalPixelB < aRow + aWidth * sizeof(uint32_t),
+                 "Running off end of buffer");
+
+      // Interpolate the individual pixels componentwise. Note that we start
+      // iteration at 1 since we don't need to apply any interpolation to the
+      // first pixel in the block, which has its final value.
+      for (size_t pixelIndex = 1; pixelIndex < finalPixelStride; ++pixelIndex) {
+        const float weight = weights[pixelIndex];
+        uint8_t* pixel = aRow + blockBytes + pixelIndex * sizeof(uint32_t);
+
+        MOZ_ASSERT(pixel < aRow + aWidth * sizeof(uint32_t), "Running off end of buffer");
+
+        for (size_t component = 0; component < sizeof(uint32_t); ++component) {
+          pixel[component] =
+            InterpolateByte(finalPixelA[component], finalPixelB[component], weight);
+        }
+      }
+    }
+
+    // For the pixels after the last final pixel in the row, there isn't a
+    // second final pixel to interpolate with, so just duplicate.
+    uint32_t* rowPixels = reinterpret_cast<uint32_t*>(aRow);
+    uint32_t pixelToDuplicate = rowPixels[lastFinalPixel];
+    for (int32_t pixelIndex = lastFinalPixel + 1;
+         pixelIndex < aWidth;
+         ++pixelIndex) {
+      MOZ_ASSERT(pixelIndex < aWidth, "Running off end of buffer");
+      rowPixels[pixelIndex] = pixelToDuplicate;
+    }
+  }
+
+  static uint8_t InterpolateByte(uint8_t aByteA, uint8_t aByteB, float aWeight)
+  {
+    return uint8_t(aByteA * aWeight + aByteB * (1.0f - aWeight));
+  }
+
+  static int32_t ImportantRowStride(uint8_t aPass)
+  {
+    MOZ_ASSERT(0 < aPass && aPass <= 7, "Invalid pass");
+
+    // The stride between important rows for each pass, with a dummy value for
+    // the nonexistent pass 0.
+    static int32_t strides[] = { 1, 8, 8, 4, 4, 2, 2, 1 };
+
+    return strides[aPass];
+  }
+
+  static bool IsImportantRow(int32_t aRow, uint8_t aPass)
+  {
+    MOZ_ASSERT(aRow >= 0);
+
+    // Whether the row is important comes down to divisibility by the stride for
+    // this pass, which is always a power of 2, so we can check using a mask.
+    int32_t mask = ImportantRowStride(aPass) - 1;
+    return (aRow & mask) == 0;
+  }
+
+  static int32_t LastImportantRow(int32_t aHeight, uint8_t aPass)
+  {
+    MOZ_ASSERT(aHeight > 0);
+
+    // We can find the last important row using the same mask trick as above.
+    int32_t lastRow = aHeight - 1;
+    int32_t mask = ImportantRowStride(aPass) - 1;
+    return lastRow - (lastRow & mask);
+  }
+
+  static size_t FinalPixelStride(uint8_t aPass)
+  {
+    MOZ_ASSERT(0 < aPass && aPass <= 7, "Invalid pass");
+
+    // The stride between the final pixels in important rows for each pass, with
+    // a dummy value for the nonexistent pass 0.
+    static size_t strides[] = { 1, 8, 4, 4, 2, 2, 1, 1 };
+
+    return strides[aPass];
+  }
+
+  static size_t LastFinalPixel(int32_t aWidth, uint8_t aPass)
+  {
+    MOZ_ASSERT(aWidth >= 0);
+
+    // Again, we can use the mask trick above to find the last important pixel.
+    int32_t lastColumn = aWidth - 1;
+    size_t mask = FinalPixelStride(aPass) - 1;
+    return lastColumn - (lastColumn & mask);
+  }
+
+  static const float* InterpolationWeights(int32_t aStride)
+  {
+    // Precalculated interpolation weights. These are used to interpolate
+    // between final pixels or between important rows. Although no interpolation
+    // is actually applied to the previous final pixel or important row value,
+    // the arrays still start with 1.0f, which is always skipped, primarily
+    // because otherwise |stride1Weights| would have zero elements.
+    static float stride8Weights[] =
+      { 1.0f, 7 / 8.0f, 6 / 8.0f, 5 / 8.0f, 4 / 8.0f, 3 / 8.0f, 2 / 8.0f, 1 / 8.0f };
+    static float stride4Weights[] = { 1.0f, 3 / 4.0f, 2 / 4.0f, 1 / 4.0f };
+    static float stride2Weights[] = { 1.0f, 1 / 2.0f };
+    static float stride1Weights[] = { 1.0f };
+
+    switch (aStride) {
+      case 8:  return stride8Weights;
+      case 4:  return stride4Weights;
+      case 2:  return stride2Weights;
+      case 1:  return stride1Weights;
+      default: MOZ_CRASH();
+    }
+  }
+
+  Next mNext;                         /// The next SurfaceFilter in the chain.
+
+  UniquePtr<uint8_t[]> mPreviousRow;  /// The last important row (i.e., row with
+                                      /// final pixel values) that got written to.
+  UniquePtr<uint8_t[]> mCurrentRow;   /// The row that's being written to right
+                                      /// now.
+  uint8_t mPass;                      /// Which ADAM7 pass we're on. Valid passes
+                                      /// are 1..7 during processing and 0 prior
+                                      /// to configuraiton.
+  int32_t mRow;                       /// The row we're currently reading.
+};
+
 } // namespace image
 } // namespace mozilla
 
 #endif // mozilla_image_SurfaceFilters_h
--- a/image/SurfacePipeFactory.h
+++ b/image/SurfacePipeFactory.h
@@ -43,19 +43,23 @@ struct FilterPipeline<Config>
  * Flags for SurfacePipeFactory, used in conjuction with the factory functions
  * in SurfacePipeFactory to enable or disable various SurfacePipe
  * functionality.
  */
 enum class SurfacePipeFlags
 {
   DEINTERLACE         = 1 << 0,  // If set, deinterlace the image.
 
-  FLIP_VERTICALLY     = 1 << 1,  // If set, flip the image vertically.
+  ADAM7_INTERPOLATE   = 1 << 1,  // If set, the caller is deinterlacing the
+                                 // image using ADAM7, and we may want to
+                                 // interpolate it for better intermediate results.
 
-  PROGRESSIVE_DISPLAY = 1 << 2   // If set, we expect the image to be displayed
+  FLIP_VERTICALLY     = 1 << 2,  // If set, flip the image vertically.
+
+  PROGRESSIVE_DISPLAY = 1 << 3   // If set, we expect the image to be displayed
                                  // progressively. This enables features that
                                  // result in a better user experience for
                                  // progressive display but which may be more
                                  // computationally expensive.
 };
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SurfacePipeFlags)
 
 class SurfacePipeFactory
@@ -94,55 +98,78 @@ public:
   {
     const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE);
     const bool flipVertically = bool(aFlags & SurfacePipeFlags::FLIP_VERTICALLY);
     const bool progressiveDisplay = bool(aFlags & SurfacePipeFlags::PROGRESSIVE_DISPLAY);
     const bool downscale = aInputSize != aOutputSize;
     const bool removeFrameRect =
       !aFrameRect.IsEqualEdges(nsIntRect(0, 0, aInputSize.width, aInputSize.height));
 
+    // Don't interpolate if we're sure we won't show this surface to the user
+    // until it's completely decoded. The final pass of an ADAM7 image doesn't
+    // need interpolation, so we only need to interpolate if we'll be displaying
+    // the image while it's still being decoded.
+    const bool adam7Interpolate = bool(aFlags & SurfacePipeFlags::ADAM7_INTERPOLATE) &&
+                                  progressiveDisplay;
+
+    if (deinterlace && adam7Interpolate) {
+      MOZ_ASSERT_UNREACHABLE("ADAM7 deinterlacing is handled by libpng");
+      return Nothing();
+    }
+
     // Construct configurations for the SurfaceFilters. Note that the order of
-    // these filters is significant. We want to deinterlace raw input rows,
-    // before any other transformations, and we want to remove the frame rect
-    // (which may involve adding blank rows or columns to the image) before any
-    // downscaling, so that the new rows and columns are taken into account.
+    // these filters is significant. We want to deinterlace or interpolate raw
+    // input rows, before any other transformations, and we want to remove the
+    // frame rect (which may involve adding blank rows or columns to the image)
+    // before any downscaling, so that the new rows and columns are taken into
+    // account.
     DeinterlacingConfig<uint32_t> deinterlacingConfig { progressiveDisplay };
+    ADAM7InterpolatingConfig interpolatingConfig;
     RemoveFrameRectConfig removeFrameRectConfig { aFrameRect };
     DownscalingConfig downscalingConfig { aInputSize, aFormat };
     SurfaceConfig surfaceConfig { aDecoder, aFrameNum, aOutputSize,
                                   aFormat, flipVertically };
 
     Maybe<SurfacePipe> pipe;
 
     if (downscale) {
       if (removeFrameRect) {
         if (deinterlace) {
           pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig,
                           downscalingConfig, surfaceConfig);
-        } else {  // (deinterlace is false)
+        } else if (adam7Interpolate) {
+          pipe = MakePipe(interpolatingConfig, removeFrameRectConfig,
+                          downscalingConfig, surfaceConfig);
+        } else {  // (deinterlace and adam7Interpolate are false)
           pipe = MakePipe(removeFrameRectConfig, downscalingConfig, surfaceConfig);
         }
       } else {  // (removeFrameRect is false)
         if (deinterlace) {
           pipe = MakePipe(deinterlacingConfig, downscalingConfig, surfaceConfig);
-        } else {  // (deinterlace is false)
+        } else if (adam7Interpolate) {
+          pipe = MakePipe(interpolatingConfig, downscalingConfig, surfaceConfig);
+        } else {  // (deinterlace and adam7Interpolate are false)
           pipe = MakePipe(downscalingConfig, surfaceConfig);
         }
       }
     } else {  // (downscale is false)
       if (removeFrameRect) {
         if (deinterlace) {
           pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig, surfaceConfig);
-        } else {  // (deinterlace is false)
+        } else if (adam7Interpolate) {
+          pipe = MakePipe(interpolatingConfig, removeFrameRectConfig, surfaceConfig);
+        } else {  // (deinterlace and adam7Interpolate are false)
           pipe = MakePipe(removeFrameRectConfig, surfaceConfig);
         }
       } else {  // (removeFrameRect is false)
         if (deinterlace) {
           pipe = MakePipe(deinterlacingConfig, surfaceConfig);
-        } else {  // (deinterlace is false)
+        } else if (adam7Interpolate) {
+          pipe = MakePipe(interpolatingConfig, surfaceConfig);
+        } else {  // (deinterlace and adam7Interpolate are false)
           pipe = MakePipe(surfaceConfig);
         }
       }
     }
 
     return pipe;
   }
 
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -11,16 +11,18 @@
 #include "nsColor.h"
 #include "nsIInputStream.h"
 #include "nsMemory.h"
 #include "nsPNGDecoder.h"
 #include "nsRect.h"
 #include "nspr.h"
 #include "png.h"
 #include "RasterImage.h"
+#include "SurfacePipeFactory.h"
+#include "mozilla/DebugOnly.h"
 #include "mozilla/Telemetry.h"
 
 #include <algorithm>
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace image {
@@ -86,28 +88,33 @@ nsPNGDecoder::AnimFrameInfo::AnimFrameIn
 }
 #endif
 
 // First 8 bytes of a PNG file
 const uint8_t
 nsPNGDecoder::pngSignatureBytes[] = { 137, 80, 78, 71, 13, 10, 26, 10 };
 
 nsPNGDecoder::nsPNGDecoder(RasterImage* aImage)
- : Decoder(aImage),
-   mPNG(nullptr), mInfo(nullptr),
-   mCMSLine(nullptr), interlacebuf(nullptr),
-   mInProfile(nullptr), mTransform(nullptr),
-   format(gfx::SurfaceFormat::UNKNOWN),
-   mHeaderBytesRead(0), mCMSMode(0),
-   mChannels(0), mFrameIsHidden(false),
-   mDisablePremultipliedAlpha(false),
-   mSuccessfulEarlyFinish(false),
-   mNumFrames(0)
-{
-}
+ : Decoder(aImage)
+ , mPNG(nullptr)
+ , mInfo(nullptr)
+ , mCMSLine(nullptr)
+ , interlacebuf(nullptr)
+ , mInProfile(nullptr)
+ , mTransform(nullptr)
+ , format(gfx::SurfaceFormat::UNKNOWN)
+ , mHeaderBytesRead(0)
+ , mCMSMode(0)
+ , mChannels(0)
+ , mPass(0)
+ , mFrameIsHidden(false)
+ , mDisablePremultipliedAlpha(false)
+ , mSuccessfulEarlyFinish(false)
+ , mNumFrames(0)
+{ }
 
 nsPNGDecoder::~nsPNGDecoder()
 {
   if (mPNG) {
     png_destroy_read_struct(&mPNG, mInfo ? &mInfo : nullptr, nullptr);
   }
   if (mCMSLine) {
     free(mCMSLine);
@@ -120,87 +127,121 @@ nsPNGDecoder::~nsPNGDecoder()
 
     // mTransform belongs to us only if mInProfile is non-null
     if (mTransform) {
       qcms_transform_release(mTransform);
     }
   }
 }
 
-void
-nsPNGDecoder::CheckForTransparency(SurfaceFormat aFormat,
-                                   const IntRect& aFrameRect)
+nsPNGDecoder::TransparencyType
+nsPNGDecoder::GetTransparencyType(SurfaceFormat aFormat,
+                                  const IntRect& aFrameRect)
 {
   // Check if the image has a transparent color in its palette.
   if (aFormat == SurfaceFormat::B8G8R8A8) {
-    PostHasTransparency();
+    return TransparencyType::eAlpha;
+  }
+  if (!IntRect(IntPoint(), GetSize()).IsEqualEdges(aFrameRect)) {
+    MOZ_ASSERT(HasAnimation());
+    return TransparencyType::eFrameRect;
   }
 
-  // If the first frame of animated image doesn't draw into the whole image,
-  // then record that it is transparent.
-  if (mNumFrames == 0 && !IntRect(IntPoint(), GetSize()).IsEqualEdges(aFrameRect)) {
-    MOZ_ASSERT(HasAnimation());
-    PostHasTransparency();
+  return TransparencyType::eNone;
+}
+
+void
+nsPNGDecoder::PostHasTransparencyIfNeeded(TransparencyType aTransparencyType)
+{
+  switch (aTransparencyType) {
+    case TransparencyType::eNone:
+      return;
+
+    case TransparencyType::eAlpha:
+      PostHasTransparency();
+      return;
+
+    case TransparencyType::eFrameRect:
+      // If the first frame of animated image doesn't draw into the whole image,
+      // then record that it is transparent. For subsequent frames, this doesn't
+      // affect transparency, because they're composited on top of all previous
+      // frames.
+      if (mNumFrames == 0) {
+        PostHasTransparency();
+      }
+      return;
   }
 }
 
-// CreateFrame() is used for both simple and animated images
+// CreateFrame() is used for both simple and animated images.
 nsresult
-nsPNGDecoder::CreateFrame(png_uint_32 aXOffset, png_uint_32 aYOffset,
-                          int32_t aWidth, int32_t aHeight,
-                          gfx::SurfaceFormat aFormat)
+nsPNGDecoder::CreateFrame(SurfaceFormat aFormat,
+                          const IntRect& aFrameRect,
+                          bool aIsInterlaced)
 {
   MOZ_ASSERT(HasSize());
   MOZ_ASSERT(!IsMetadataDecode());
 
-  IntRect frameRect(aXOffset, aYOffset, aWidth, aHeight);
-  CheckForTransparency(aFormat, frameRect);
+  // Check if we have transparency, and send notifications if needed.
+  auto transparency = GetTransparencyType(aFormat, aFrameRect);
+  PostHasTransparencyIfNeeded(transparency);
+  SurfaceFormat format = transparency == TransparencyType::eNone
+                       ? SurfaceFormat::B8G8R8X8
+                       : SurfaceFormat::B8G8R8A8;
 
   // Make sure there's no animation or padding if we're downscaling.
+  MOZ_ASSERT_IF(mDownscaler, mNumFrames == 0);
   MOZ_ASSERT_IF(mDownscaler, !GetImageMetadata().HasAnimation());
-  MOZ_ASSERT_IF(mDownscaler,
-                IntRect(IntPoint(), GetSize()).IsEqualEdges(frameRect));
+  MOZ_ASSERT_IF(mDownscaler, transparency != TransparencyType::eFrameRect);
 
   IntSize targetSize = mDownscaler ? mDownscaler->TargetSize()
                                    : GetSize();
-  IntRect targetFrameRect = mDownscaler ? IntRect(IntPoint(), targetSize)
-                                        : frameRect;
-  nsresult rv = AllocateFrame(mNumFrames, targetSize, targetFrameRect, aFormat);
-  if (NS_FAILED(rv)) {
-    return rv;
+
+  // If this image is interlaced, we can display better quality intermediate
+  // results to the user by post processing them with ADAM7InterpolatingFilter.
+  SurfacePipeFlags pipeFlags = aIsInterlaced
+                             ? SurfacePipeFlags::ADAM7_INTERPOLATE
+                             : SurfacePipeFlags();
+
+  if (mNumFrames == 0) {
+    // The first frame may be displayed progressively.
+    pipeFlags |= SurfacePipeFlags::PROGRESSIVE_DISPLAY;
   }
 
-  mFrameRect = frameRect;
+  Maybe<SurfacePipe> pipe =
+    SurfacePipeFactory::CreateSurfacePipe(this, mNumFrames, GetSize(), targetSize,
+                                          aFrameRect, format, pipeFlags);
+
+  if (!pipe) {
+    mPipe = SurfacePipe();
+    return NS_ERROR_FAILURE;
+  }
+
+  mPipe = Move(*pipe);
+
+  mFrameRect = aFrameRect;
+  mPass = 0;
 
   MOZ_LOG(sPNGDecoderAccountingLog, LogLevel::Debug,
          ("PNGDecoderAccounting: nsPNGDecoder::CreateFrame -- created "
           "image frame with %dx%d pixels for decoder %p",
-          aWidth, aHeight, this));
+          aFrameRect.width, aFrameRect.height, this));
 
 #ifdef PNG_APNG_SUPPORTED
   if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL)) {
     mAnimInfo = AnimFrameInfo(mPNG, mInfo);
 
     if (mAnimInfo.mDispose == DisposalMethod::CLEAR) {
       // We may have to display the background under this image during
       // animation playback, so we regard it as transparent.
       PostHasTransparency();
     }
   }
 #endif
 
-  if (mDownscaler) {
-    bool hasAlpha = aFormat != SurfaceFormat::B8G8R8X8;
-    rv = mDownscaler->BeginFrame(frameRect.Size(), Nothing(),
-                                 mImageData, hasAlpha);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-  }
-
   return NS_OK;
 }
 
 // set timeout and frame disposal method for the current frame
 void
 nsPNGDecoder::EndImageFrame()
 {
   if (mFrameIsHidden) {
@@ -210,17 +251,17 @@ nsPNGDecoder::EndImageFrame()
   mNumFrames++;
 
   Opacity opacity = Opacity::SOME_TRANSPARENCY;
   if (format == gfx::SurfaceFormat::B8G8R8X8) {
     opacity = Opacity::FULLY_OPAQUE;
   }
 
   PostFrameStop(opacity, mAnimInfo.mDispose, mAnimInfo.mTimeout,
-                mAnimInfo.mBlend);
+                mAnimInfo.mBlend, Some(mFrameRect));
 }
 
 void
 nsPNGDecoder::InitInternal()
 {
   mCMSMode = gfxPlatform::GetCMSMode();
   if (GetSurfaceFlags() & SurfaceFlags::NO_COLORSPACE_CONVERSION) {
     mCMSMode = eCMSMode_Off;
@@ -453,17 +494,16 @@ PNGGetColorProfile(png_structp png_ptr, 
   }
 
   return profile;
 }
 
 void
 nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
 {
-//  int number_passes;   NOT USED
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type, compression_type, filter_type;
   unsigned int channels;
 
   png_bytep trans = nullptr;
   int num_trans = 0;
 
   nsPNGDecoder* decoder =
@@ -473,18 +513,20 @@ nsPNGDecoder::info_callback(png_structp 
   png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                &interlace_type, &compression_type, &filter_type);
 
   // Are we too big?
   if (width > MOZ_PNG_MAX_DIMENSION || height > MOZ_PNG_MAX_DIMENSION) {
     png_longjmp(decoder->mPNG, 1);
   }
 
+  const IntRect frameRect(0, 0, width, height);
+
   // Post our size to the superclass
-  decoder->PostSize(width, height);
+  decoder->PostSize(frameRect.width, frameRect.height);
   if (decoder->HasError()) {
     // Setting the size led to an error.
     png_longjmp(decoder->mPNG, 1);
   }
 
   if (color_type == PNG_COLOR_TYPE_PALETTE) {
     png_set_expand(png_ptr);
   }
@@ -559,19 +601,19 @@ nsPNGDecoder::info_callback(png_structp 
       if (color_type & PNG_COLOR_MASK_ALPHA || num_trans) {
         decoder->mTransform = gfxPlatform::GetCMSRGBATransform();
       } else {
         decoder->mTransform = gfxPlatform::GetCMSRGBTransform();
       }
     }
   }
 
-  // let libpng expand interlaced images
-  if (interlace_type == PNG_INTERLACE_ADAM7) {
-    // number_passes =
+  // Let libpng expand interlaced images.
+  const bool isInterlaced = interlace_type == PNG_INTERLACE_ADAM7;
+  if (isInterlaced) {
     png_set_interlace_handling(png_ptr);
   }
 
   // now all of those things we set above are used to update various struct
   // members and whatnot, after which we can get channels, rowbytes, etc.
   png_read_update_info(png_ptr, info_ptr);
   decoder->mChannels = channels = png_get_channels(png_ptr, info_ptr);
 
@@ -590,30 +632,30 @@ nsPNGDecoder::info_callback(png_structp 
 #ifdef PNG_APNG_SUPPORTED
   bool isAnimated = png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL);
   if (isAnimated) {
     decoder->PostIsAnimated(GetNextFrameDelay(png_ptr, info_ptr));
 
     if (decoder->mDownscaler && !decoder->IsFirstFrameDecode()) {
       MOZ_ASSERT_UNREACHABLE("Doing downscale-during-decode "
                              "for an animated image?");
-      decoder->mDownscaler.reset();
+      png_longjmp(decoder->mPNG, 1);  // Abort the decode.
     }
   }
 #endif
 
   if (decoder->IsMetadataDecode()) {
     // If we are animated then the first frame rect is either: 1) the whole image
     // if the IDAT chunk is part of the animation 2) the frame rect of the first
     // fDAT chunk otherwise. If we are not animated then we want to make sure to
     // call PostHasTransparency in the metadata decode if we need to. So it's okay
     // to pass IntRect(0, 0, width, height) here for animated images; they will
     // call with the proper first frame rect in the full decode.
-    decoder->CheckForTransparency(decoder->format,
-                                  IntRect(0, 0, width, height));
+    auto transparency = decoder->GetTransparencyType(decoder->format, frameRect);
+    decoder->PostHasTransparencyIfNeeded(transparency);
 
     // We have the metadata we're looking for, so we don't need to decode any
     // further.
     decoder->mSuccessfulEarlyFinish = true;
     png_longjmp(decoder->mPNG, 1);
   }
 
 #ifdef PNG_APNG_SUPPORTED
@@ -621,146 +663,84 @@ nsPNGDecoder::info_callback(png_structp 
     png_set_progressive_frame_fn(png_ptr, nsPNGDecoder::frame_info_callback,
                                  nullptr);
   }
 
   if (png_get_first_frame_is_hidden(png_ptr, info_ptr)) {
     decoder->mFrameIsHidden = true;
   } else {
 #endif
-    nsresult rv = decoder->CreateFrame(0, 0, width, height, decoder->format);
+    nsresult rv = decoder->CreateFrame(decoder->format, frameRect, isInterlaced);
     if (NS_FAILED(rv)) {
       png_longjmp(decoder->mPNG, 5); // NS_ERROR_OUT_OF_MEMORY
     }
     MOZ_ASSERT(decoder->mImageData, "Should have a buffer now");
 #ifdef PNG_APNG_SUPPORTED
   }
 #endif
 
-  if (decoder->mTransform &&
-      (channels <= 2 || interlace_type == PNG_INTERLACE_ADAM7)) {
+  if (decoder->mTransform && (channels <= 2 || isInterlaced)) {
     uint32_t bpp[] = { 0, 3, 4, 3, 4 };
     decoder->mCMSLine =
-      (uint8_t*)malloc(bpp[channels] * width);
+      static_cast<uint8_t*>(malloc(bpp[channels] * frameRect.width));
     if (!decoder->mCMSLine) {
       png_longjmp(decoder->mPNG, 5); // NS_ERROR_OUT_OF_MEMORY
     }
   }
 
   if (interlace_type == PNG_INTERLACE_ADAM7) {
-    if (height < INT32_MAX / (width * channels)) {
-      decoder->interlacebuf = (uint8_t*)malloc(channels * width * height);
+    if (frameRect.height < INT32_MAX / (frameRect.width * int32_t(channels))) {
+      const size_t bufferSize = channels * frameRect.width * frameRect.height;
+      decoder->interlacebuf = static_cast<uint8_t*>(malloc(bufferSize));
     }
     if (!decoder->interlacebuf) {
       png_longjmp(decoder->mPNG, 5); // NS_ERROR_OUT_OF_MEMORY
     }
   }
 }
 
 void
-nsPNGDecoder::PostPartialInvalidation(const IntRect& aInvalidRegion)
-{
-  if (!mDownscaler) {
-    PostInvalidation(aInvalidRegion);
-    return;
-  }
-
-  if (!mDownscaler->HasInvalidation()) {
-    return;
-  }
-
-  DownscalerInvalidRect invalidRect = mDownscaler->TakeInvalidRect();
-  PostInvalidation(invalidRect.mOriginalSizeRect,
-                   Some(invalidRect.mTargetSizeRect));
-}
-
-void
-nsPNGDecoder::PostFullInvalidation()
+nsPNGDecoder::PostInvalidationIfNeeded()
 {
-  PostInvalidation(mFrameRect);
-
-  if (mDownscaler) {
-    mDownscaler->ResetForNextProgressivePass();
-  }
-}
-
-static void
-InterpolateInterlacedPNG(const int aPass, const bool aHasAlpha,
-                         const uint32_t aWidth, const uint32_t aHeight,
-                         uint8_t* aImageData)
-{
-  // At this point we have a completed pass of an interlaced image in
-  // imageData as an array of uint8_t ARGB or XRGB pixels, optionally
-  // premultiplied, 4 bytes per pixel. If there are leftover partial
-  // blocks at the right edge or bottom of the image, we just use the
-  // uninterpolated pixels that libpng gave us.
-  //
-  // See Bug #75077, Interpolation of interlaced PNG
-  // See https://en.wikipedia.org/wiki/Bilinear_interpolation
-  //
-  // Note: this doesn't work when downscaling so we simply show
-  // the uninterpolated blocks that libpng gives us.
-  //
-  // Don't try to interpolate images that are less than 8 columns wide
-  // or 8 rows high; do only square passes (0, 2, 4)
-  if ((aPass != 0 && aPass != 2 && aPass != 4) || aWidth < 8 || aHeight < 8) {
+  Maybe<SurfaceInvalidRect> invalidRect = mPipe.TakeInvalidRect();
+  if (!invalidRect) {
     return;
   }
 
-  /* Block dimensions are defined by the PNG specification */
-  uint32_t block_width[]  = { 8, 4, 4, 2, 2 };
-  uint32_t bw = block_width[aPass];
-  uint32_t bh = bw;
-
-  bool first_component = aHasAlpha ? 0: 1;
+  PostInvalidation(invalidRect->mInputSpaceRect,
+                   Some(invalidRect->mOutputSpaceRect));
+}
 
-  // Reduced version of the PNG_PASS_ROW_SHIFT(pass) macro in libpng/png.h
-  // Only works with square passes 0, 2, and 4
-  uint32_t divisor_shift = 3 - (aPass >> 1);
-
-  // Loop over blocks
-  for (uint32_t y = 0; y < aHeight - bh; y += bh) {
-    for (uint32_t x = 0; x < aWidth - bw; x += bw) {
-      // (x,y) is the top left corner of the block
-      // topleft is the first component of the top left pixel of the block
-      uint8_t* topleft = aImageData + 4 * (x + aWidth * y);
+static NextPixel<uint32_t>
+PackRGBPixelAndAdvance(uint8_t*& aRawPixelInOut)
+{
+  const uint32_t pixel =
+    gfxPackedPixel(0xFF, aRawPixelInOut[0], aRawPixelInOut[1], aRawPixelInOut[2]);
+  aRawPixelInOut += 3;
+  return AsVariant(pixel);
+}
 
-      // Loop over component=[A,]R,G,B
-      for (uint32_t component = first_component; component < 4; component++) {
-        if (x == 0) {
-          // Interpolate ARGB along the left side of the block
-          uint32_t top = *(topleft + component);
-          uint32_t bottom = *(topleft + component + (bh * 4 * aWidth));
-          for (uint32_t j = 1; j < bh; j++) {
-            *(topleft + component + j * 4 * aWidth) =
-              ((top * (bh - j) + bottom * j) >> divisor_shift) & 0xff;
-          }
-        }
+static NextPixel<uint32_t>
+PackRGBAPixelAndAdvance(uint8_t*& aRawPixelInOut)
+{
+  const uint32_t pixel =
+    gfxPackedPixel(aRawPixelInOut[3], aRawPixelInOut[0],
+                   aRawPixelInOut[1], aRawPixelInOut[2]);
+  aRawPixelInOut += 4;
+  return AsVariant(pixel);
+}
 
-        // Interpolate ARGB along the right side of the block
-        uint32_t top = *(topleft + component + 4 * bw);
-        uint32_t bottom = *(topleft + component + 4 * (bw + (bh * aWidth)));
-        for (uint32_t j = 1; j < bh; j++) {
-          *(topleft + component + 4 * (bw + j * aWidth)) =
-          ((top * (bh - j) + bottom * j) >> divisor_shift) & 0xff;
-        }
-
-        // Interpolate ARGB in the X-direction along the top edge
-        // and within the block
-        for (uint32_t j = 0; j < bh; j++) {
-          uint32_t left = *(topleft + component + 4 * j * aWidth);
-          uint32_t right = *(topleft + component + 4 * (bw + j * aWidth));
-          for (uint32_t i = 1; i < bw; i++) {
-            *(topleft + component + 4 * (i + j * aWidth)) =
-            ((left * (bw - i) + right * i) >> divisor_shift) & 0xff;
-          } // i
-        } // j
-      } // component
-    } // x
-  } // y
+static NextPixel<uint32_t>
+PackUnpremultipliedRGBAPixelAndAdvance(uint8_t*& aRawPixelInOut)
+{
+  const uint32_t pixel =
+    gfxPackedPixelNoPreMultiply(aRawPixelInOut[3], aRawPixelInOut[0],
+                                aRawPixelInOut[1], aRawPixelInOut[2]);
+  aRawPixelInOut += 4;
+  return AsVariant(pixel);
 }
 
 void
 nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
                            png_uint_32 row_num, int pass)
 {
   /* libpng comments:
    *
@@ -785,147 +765,119 @@ nsPNGDecoder::row_callback(png_structp p
    * where old_row is what was displayed for previous rows.  Note
    * that the first pass (pass == 0 really) will completely cover
    * the old row, so the rows do not have to be initialized.  After
    * the first pass (and only for interlaced images), you will have
    * to pass the current row, and the function will combine the
    * old row and the new row.
    */
   nsPNGDecoder* decoder =
-               static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));
+    static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));
 
-  // skip this frame
   if (decoder->mFrameIsHidden) {
-    return;
-  }
-
-  if (row_num >= static_cast<png_uint_32>(decoder->mFrameRect.height)) {
-    return;
+    return;  // Skip this frame.
   }
 
-  bool lastRow =
-    row_num == static_cast<png_uint_32>(decoder->mFrameRect.height) - 1;
+  while (pass > decoder->mPass) {
+    // Advance to the next pass. We may have to do this multiple times because
+    // libpng will skip passes if the image is so small that no pixels have
+    // changed on a given pass, but ADAM7InterpolatingFilter needs to be reset
+    // once for every pass to perform interpolation properly.
+    decoder->mPipe.ResetToFirstRow();
+    decoder->mPass++;
+  }
 
-  if (!new_row && !decoder->mDownscaler && !lastRow) {
-    // If |new_row| is null, that indicates that this is an interlaced image
-    // and |row_callback| is being called for a row that hasn't changed.
-    // Ordinarily we don't need to do anything in this case, but if we're
-    // downscaling, the downscaler doesn't store the rows from previous passes,
-    // so we still need to process the row.  If |lastRow| is true we need
-    // to finish the interlace pass.
+  const png_uint_32 height = static_cast<png_uint_32>(decoder->mFrameRect.height);
+
+  if (row_num >= height) {
+    // Bail if we receive extra rows. This is especially important because if we
+    // didn't, we might overflow the deinterlacing buffer.
+    MOZ_ASSERT_UNREACHABLE("libpng producing extra rows?");
     return;
   }
 
-  int32_t width = decoder->mFrameRect.width;
-  uint32_t iwidth = decoder->mFrameRect.width;
+  // Note that |new_row| may be null here, indicating that this is an interlaced
+  // image and |row_callback| is being called for a row that hasn't changed.
+  MOZ_ASSERT_IF(!new_row, decoder->interlacebuf);
+  uint8_t* rowToWrite = new_row;
 
-  png_bytep line = new_row;
   if (decoder->interlacebuf) {
-    line = decoder->interlacebuf + (row_num * decoder->mChannels * width);
-    png_progressive_combine_row(png_ptr, line, new_row);
+    uint32_t width = uint32_t(decoder->mFrameRect.width);
+
+    // We'll output the deinterlaced version of the row.
+    rowToWrite = decoder->interlacebuf + (row_num * decoder->mChannels * width);
+
+    // Update the deinterlaced version of this row with the new data.
+    png_progressive_combine_row(png_ptr, rowToWrite, new_row);
   }
 
-  uint32_t bpr = width * sizeof(uint32_t);
-  uint32_t* cptr32 = decoder->mDownscaler
-    ? reinterpret_cast<uint32_t*>(decoder->mDownscaler->RowBuffer())
-    : reinterpret_cast<uint32_t*>(decoder->mImageData + (row_num*bpr));
+  decoder->WriteRow(rowToWrite);
+}
+
+void
+nsPNGDecoder::WriteRow(uint8_t* aRow)
+{
+  MOZ_ASSERT(aRow);
+
+  uint8_t* rowToWrite = aRow;
+  uint32_t width = uint32_t(mFrameRect.width);
 
-  if (decoder->mTransform) {
-    if (decoder->mCMSLine) {
-      qcms_transform_data(decoder->mTransform, line, decoder->mCMSLine,
-                          iwidth);
-      // copy alpha over
-      uint32_t channels = decoder->mChannels;
-      if (channels == 2 || channels == 4) {
-        for (uint32_t i = 0; i < iwidth; i++)
-          decoder->mCMSLine[4 * i + 3] = line[channels * i + channels - 1];
+  // Apply color management to the row, if necessary, before writing it out.
+  if (mTransform) {
+    if (mCMSLine) {
+      qcms_transform_data(mTransform, rowToWrite, mCMSLine, width);
+
+      // Copy alpha over.
+      if (mChannels == 2 || mChannels == 4) {
+        for (uint32_t i = 0; i < width; ++i) {
+          mCMSLine[4 * i + 3] = rowToWrite[mChannels * i + mChannels - 1];
+        }
       }
-      line = decoder->mCMSLine;
+
+      rowToWrite = mCMSLine;
     } else {
-      qcms_transform_data(decoder->mTransform, line, line, iwidth);
+      qcms_transform_data(mTransform, rowToWrite, rowToWrite, width);
     }
   }
 
-  switch (decoder->format) {
-    case gfx::SurfaceFormat::B8G8R8X8: {
-      // counter for while() loops below
-      uint32_t idx = iwidth;
-
-      // copy as bytes until source pointer is 32-bit-aligned
-      for (; (NS_PTR_TO_UINT32(line) & 0x3) && idx; --idx) {
-        *cptr32++ = gfxPackedPixel(0xFF, line[0], line[1], line[2]);
-        line += 3;
-      }
-
-      // copy pixels in blocks of 4
-      while (idx >= 4) {
-        GFX_BLOCK_RGB_TO_FRGB(line, cptr32);
-        idx    -=  4;
-        line   += 12;
-        cptr32 +=  4;
-      }
+  // Write this row to the SurfacePipe.
+  DebugOnly<WriteState> result = WriteState::FAILURE;
+  switch (format) {
+    case SurfaceFormat::B8G8R8X8:
+      result = mPipe.WritePixelsToRow<uint32_t>([&]{
+        return PackRGBPixelAndAdvance(rowToWrite);
+      });
+      break;
 
-      // copy remaining pixel(s)
-      while (idx--) {
-        // 32-bit read of final pixel will exceed buffer, so read bytes
-        *cptr32++ = gfxPackedPixel(0xFF, line[0], line[1], line[2]);
-        line += 3;
+    case SurfaceFormat::B8G8R8A8:
+      if (mDisablePremultipliedAlpha) {
+        result = mPipe.WritePixelsToRow<uint32_t>([&]{
+          return PackUnpremultipliedRGBAPixelAndAdvance(rowToWrite);
+        });
+      } else {
+        result = mPipe.WritePixelsToRow<uint32_t>([&]{
+          return PackRGBAPixelAndAdvance(rowToWrite);
+        });
       }
-    }
-    break;
-    case gfx::SurfaceFormat::B8G8R8A8: {
-      if (!decoder->mDisablePremultipliedAlpha) {
-        for (uint32_t x=width; x>0; --x) {
-          *cptr32++ = gfxPackedPixel(line[3], line[0], line[1], line[2]);
-          line += 4;
-        }
-      } else {
-        for (uint32_t x=width; x>0; --x) {
-          *cptr32++ = gfxPackedPixelNoPreMultiply(line[3], line[0], line[1],
-                                                  line[2]);
-          line += 4;
-        }
-      }
-    }
-    break;
+      break;
+
     default:
-      png_longjmp(decoder->mPNG, 1);
+      png_longjmp(mPNG, 1);  // Abort the decode.
   }
 
-  if (decoder->mDownscaler) {
-    decoder->mDownscaler->CommitRow();
-  }
+  MOZ_ASSERT(WriteState(result) != WriteState::FAILURE);
 
-  if (!decoder->interlacebuf) {
-    // Do line-by-line partial invalidations for non-interlaced images.
-    decoder->PostPartialInvalidation(IntRect(0, row_num, width, 1));
-  } else if (lastRow) {
-    // Do only one full image invalidation for each even pass. (Bug 1187569)
-    if (decoder->mDownscaler) {
-      decoder->PostFullInvalidation();
-    } else if (pass % 2 == 0) {
-
-      const bool hasAlpha = decoder->format != SurfaceFormat::B8G8R8X8;
-      InterpolateInterlacedPNG(pass, hasAlpha,
-                               static_cast<uint32_t>(width),
-                               decoder->mFrameRect.height,
-                               decoder->mImageData);
-      decoder->PostFullInvalidation();
-    }
-  }
+  PostInvalidationIfNeeded();
 }
 
 #ifdef PNG_APNG_SUPPORTED
 // got the header of a new frame that's coming
 void
 nsPNGDecoder::frame_info_callback(png_structp png_ptr, png_uint_32 frame_num)
 {
-  png_uint_32 x_offset, y_offset;
-  int32_t width, height;
-
   nsPNGDecoder* decoder =
                static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));
 
   // old frame is done
   decoder->EndImageFrame();
 
   if (!decoder->mFrameIsHidden && decoder->IsFirstFrameDecode()) {
     // We're about to get a second non-hidden frame, but we only want the first.
@@ -933,23 +885,24 @@ nsPNGDecoder::frame_info_callback(png_st
     decoder->PostDecodeDone();
     decoder->mSuccessfulEarlyFinish = true;
     png_longjmp(decoder->mPNG, 1);
   }
 
   // Only the first frame can be hidden, so unhide unconditionally here.
   decoder->mFrameIsHidden = false;
 
-  x_offset = png_get_next_frame_x_offset(png_ptr, decoder->mInfo);
-  y_offset = png_get_next_frame_y_offset(png_ptr, decoder->mInfo);
-  width = png_get_next_frame_width(png_ptr, decoder->mInfo);
-  height = png_get_next_frame_height(png_ptr, decoder->mInfo);
+  const IntRect frameRect(png_get_next_frame_x_offset(png_ptr, decoder->mInfo),
+                          png_get_next_frame_y_offset(png_ptr, decoder->mInfo),
+                          png_get_next_frame_width(png_ptr, decoder->mInfo),
+                          png_get_next_frame_height(png_ptr, decoder->mInfo));
 
-  nsresult rv =
-    decoder->CreateFrame(x_offset, y_offset, width, height, decoder->format);
+  const bool isInterlaced = bool(decoder->interlacebuf);
+
+  nsresult rv = decoder->CreateFrame(decoder->format, frameRect, isInterlaced);
   if (NS_FAILED(rv)) {
     png_longjmp(decoder->mPNG, 5); // NS_ERROR_OUT_OF_MEMORY
   }
   MOZ_ASSERT(decoder->mImageData, "Should have a buffer now");
 }
 #endif
 
 void
--- a/image/decoders/nsPNGDecoder.h
+++ b/image/decoders/nsPNGDecoder.h
@@ -3,45 +3,60 @@
  * 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/. */
 
 #ifndef mozilla_image_decoders_nsPNGDecoder_h
 #define mozilla_image_decoders_nsPNGDecoder_h
 
 #include "Decoder.h"
-
-#include "gfxTypes.h"
-
-#include "nsCOMPtr.h"
-
 #include "png.h"
-
 #include "qcms.h"
+#include "SurfacePipe.h"
 
 namespace mozilla {
 namespace image {
 class RasterImage;
 
 class nsPNGDecoder : public Decoder
 {
 public:
   virtual ~nsPNGDecoder();
 
   virtual void InitInternal() override;
   virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
   virtual Telemetry::ID SpeedHistogram() override;
 
-  nsresult CreateFrame(png_uint_32 aXOffset, png_uint_32 aYOffset,
-                       int32_t aWidth, int32_t aHeight,
-                       gfx::SurfaceFormat aFormat);
+private:
+  friend class DecoderFactory;
+  friend class nsICODecoder;
+
+  // Decoders should only be instantiated via DecoderFactory.
+  // XXX(seth): nsICODecoder is temporarily an exception to this rule.
+  explicit nsPNGDecoder(RasterImage* aImage);
+
+  nsresult CreateFrame(gfx::SurfaceFormat aFormat,
+                       const gfx::IntRect& aFrameRect,
+                       bool aIsInterlaced);
   void EndImageFrame();
 
-  void CheckForTransparency(gfx::SurfaceFormat aFormat,
-                            const gfx::IntRect& aFrameRect);
+  enum class TransparencyType
+  {
+    eNone,
+    eAlpha,
+    eFrameRect
+  };
+
+  TransparencyType GetTransparencyType(gfx::SurfaceFormat aFormat,
+                                       const gfx::IntRect& aFrameRect);
+  void PostHasTransparencyIfNeeded(TransparencyType aTransparencyType);
+
+  void PostInvalidationIfNeeded();
+
+  void WriteRow(uint8_t* aRow);
 
   // Check if PNG is valid ICO (32bpp RGBA)
   // http://blogs.msdn.com/b/oldnewthing/archive/2010/10/22/10079192.aspx
   bool IsValidICO() const
   {
     // If there are errors in the call to png_get_IHDR, the error_callback in
     // nsPNGDecoder.cpp is called.  In this error callback we do a longjmp, so
     // we need to save the jump buffer here. Oterwise we'll end up without a
@@ -64,27 +79,16 @@ public:
       return ((png_color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
                png_color_type == PNG_COLOR_TYPE_RGB) &&
               png_bit_depth == 8);
     } else {
       return false;
     }
   }
 
-private:
-  friend class DecoderFactory;
-  friend class nsICODecoder;
-
-  // Decoders should only be instantiated via DecoderFactory.
-  // XXX(seth): nsICODecoder is temporarily an exception to this rule.
-  explicit nsPNGDecoder(RasterImage* aImage);
-
-  void PostPartialInvalidation(const IntRect& aInvalidRegion);
-  void PostFullInvalidation();
-
 public:
   png_structp mPNG;
   png_infop mInfo;
   nsIntRect mFrameRect;
   uint8_t* mCMSLine;
   uint8_t* interlacebuf;
   qcms_profile* mInProfile;
   qcms_transform* mTransform;
@@ -94,16 +98,17 @@ public:
   // For metadata decodes.
   uint8_t mSizeBytes[8]; // Space for width and height, both 4 bytes
   uint32_t mHeaderBytesRead;
 
   // whether CMS or premultiplied alpha are forced off
   uint32_t mCMSMode;
 
   uint8_t mChannels;
+  uint8_t mPass;
   bool mFrameIsHidden;
   bool mDisablePremultipliedAlpha;
   bool mSuccessfulEarlyFinish;
 
   struct AnimFrameInfo
   {
     AnimFrameInfo();
 #ifdef PNG_APNG_SUPPORTED
@@ -112,16 +117,18 @@ public:
 
     DisposalMethod mDispose;
     BlendMethod mBlend;
     int32_t mTimeout;
   };
 
   AnimFrameInfo mAnimInfo;
 
+  SurfacePipe mPipe;  /// The SurfacePipe used to write to the output surface.
+
   // The number of frames we've finished.
   uint32_t mNumFrames;
 
   // libpng callbacks
   // We put these in the class so that they can access protected members.
   static void PNGAPI info_callback(png_structp png_ptr, png_infop info_ptr);
   static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row,
                                   png_uint_32 row_num, int pass);
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -11,23 +11,24 @@
 #include "prenv.h"
 
 #include "gfx2DGlue.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
 #include "gfxAlphaRecovery.h"
 
 #include "GeckoProfiler.h"
+#include "MainThreadUtils.h"
+#include "mozilla/CheckedInt.h"
+#include "mozilla/gfx/Tools.h"
 #include "mozilla/Likely.h"
-#include "MainThreadUtils.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/Telemetry.h"
 #include "nsMargin.h"
 #include "nsThreadUtils.h"
-#include "mozilla/CheckedInt.h"
-#include "mozilla/gfx/Tools.h"
 
 
 namespace mozilla {
 
 using namespace gfx;
 
 namespace image {
 
@@ -392,22 +393,29 @@ imgFrame::Optimize()
         return NS_OK;
       }
     }
 
     // if it's not RGB24/ARGB32, don't optimize, but we never hit this at the
     // moment
   }
 
+  const bool usedSingleColorOptimizationUsefully = mSinglePixel &&
+                                                   mFrameRect.Area() > 1;
+  Telemetry::Accumulate(Telemetry::IMAGE_OPTIMIZE_TO_SINGLE_COLOR_USED,
+                        usedSingleColorOptimizationUsefully);
+
 #ifdef ANDROID
   SurfaceFormat optFormat = gfxPlatform::GetPlatform()
     ->Optimal2DFormatForContent(gfxContentType::COLOR);
 
   if (mFormat != SurfaceFormat::B8G8R8A8 &&
       optFormat == SurfaceFormat::R5G6B5_UINT16) {
+    Telemetry::Accumulate(Telemetry::IMAGE_OPTIMIZE_TO_565_USED, true);
+
     RefPtr<VolatileBuffer> buf =
       AllocateBufferForImage(mFrameRect.Size(), optFormat);
     if (!buf) {
       return NS_OK;
     }
 
     RefPtr<DataSourceSurface> surf =
       CreateLockedSurface(buf, mFrameRect.Size(), optFormat);
@@ -633,28 +641,30 @@ imgFrame::ImageUpdatedInternal(const nsI
 
   return NS_OK;
 }
 
 void
 imgFrame::Finish(Opacity aFrameOpacity /* = Opacity::SOME_TRANSPARENCY */,
                  DisposalMethod aDisposalMethod /* = DisposalMethod::KEEP */,
                  int32_t aRawTimeout /* = 0 */,
-                 BlendMethod aBlendMethod /* = BlendMethod::OVER */)
+                 BlendMethod aBlendMethod /* = BlendMethod::OVER */,
+                 const Maybe<IntRect>& aBlendRect /* = Nothing() */)
 {
   MonitorAutoLock lock(mMonitor);
   MOZ_ASSERT(mLockCount > 0, "Image data should be locked");
 
   if (aFrameOpacity == Opacity::FULLY_OPAQUE) {
     mHasNoAlpha = true;
   }
 
   mDisposalMethod = aDisposalMethod;
   mTimeout = aRawTimeout;
   mBlendMethod = aBlendMethod;
+  mBlendRect = aBlendRect;
   ImageUpdatedInternal(GetRect());
   mFinished = true;
 
   // The image is now complete, wake up anyone who's waiting.
   mMonitor.NotifyAll();
 }
 
 uint32_t
@@ -920,17 +930,17 @@ imgFrame::GetAnimationData() const
   } else {
     uint32_t length;
     GetImageDataInternal(&data, &length);
   }
 
   bool hasAlpha = mFormat == SurfaceFormat::B8G8R8A8;
 
   return AnimationData(data, PaletteDataLength(), mTimeout, GetRect(),
-                       mBlendMethod, mDisposalMethod, hasAlpha);
+                       mBlendMethod, mBlendRect, mDisposalMethod, hasAlpha);
 }
 
 void
 imgFrame::Abort()
 {
   MonitorAutoLock lock(mMonitor);
 
   mAborted = true;
--- a/image/imgFrame.h
+++ b/image/imgFrame.h
@@ -2,16 +2,17 @@
  *
  * 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/. */
 
 #ifndef mozilla_image_imgFrame_h
 #define mozilla_image_imgFrame_h
 
+#include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Move.h"
 #include "mozilla/VolatileBuffer.h"
 #include "gfxDrawable.h"
 #include "imgIContainer.h"
 #include "MainThreadUtils.h"
 
@@ -52,32 +53,34 @@ enum class Opacity : uint8_t {
  * It includes pointers to the raw image data of the underlying imgFrame, but
  * does not own that data. A RawAccessFrameRef for the underlying imgFrame must
  * outlive the AnimationData for it to remain valid.
  */
 struct AnimationData
 {
   AnimationData(uint8_t* aRawData, uint32_t aPaletteDataLength,
                 int32_t aRawTimeout, const nsIntRect& aRect,
-                BlendMethod aBlendMethod, DisposalMethod aDisposalMethod,
-                bool aHasAlpha)
+                BlendMethod aBlendMethod, const Maybe<gfx::IntRect>& aBlendRect,
+                DisposalMethod aDisposalMethod, bool aHasAlpha)
     : mRawData(aRawData)
     , mPaletteDataLength(aPaletteDataLength)
     , mRawTimeout(aRawTimeout)
     , mRect(aRect)
     , mBlendMethod(aBlendMethod)
+    , mBlendRect(aBlendRect)
     , mDisposalMethod(aDisposalMethod)
     , mHasAlpha(aHasAlpha)
   { }
 
   uint8_t* mRawData;
   uint32_t mPaletteDataLength;
   int32_t mRawTimeout;
   nsIntRect mRect;
   BlendMethod mBlendMethod;
+  Maybe<gfx::IntRect> mBlendRect;
   DisposalMethod mDisposalMethod;
   bool mHasAlpha;
 };
 
 class imgFrame
 {
   typedef gfx::Color Color;
   typedef gfx::DataSourceSurface DataSourceSurface;
@@ -165,21 +168,25 @@ public:
    *                         from the compositing frame before the next frame is
    *                         displayed.
    * @param aRawTimeout      For animation frames, the timeout in milliseconds
    *                         before the next frame is displayed. This timeout is
    *                         not necessarily the timeout that will actually be
    *                         used; see FrameAnimator::GetTimeoutForFrame.
    * @param aBlendMethod     For animation frames, a blending method to be used
    *                         when compositing this frame.
+   * @param aBlendRect       For animation frames, if present, the subrect in
+   *                         which @aBlendMethod applies. Outside of this
+   *                         subrect, BlendMethod::OVER is always used.
    */
   void Finish(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY,
               DisposalMethod aDisposalMethod = DisposalMethod::KEEP,
               int32_t aRawTimeout = 0,
-              BlendMethod aBlendMethod = BlendMethod::OVER);
+              BlendMethod aBlendMethod = BlendMethod::OVER,
+              const Maybe<IntRect>& aBlendRect = Nothing());
 
   /**
    * Mark this imgFrame as aborted. This informs the imgFrame that if it isn't
    * completely decoded now, it never will be.
    *
    * You must always call either Finish() or Abort() before releasing the last
    * RawAccessFrameRef pointing to an imgFrame.
    */
@@ -304,16 +311,17 @@ private: // data
   //! Number of RawAccessFrameRefs currently alive for this imgFrame.
   int32_t mLockCount;
 
   //! Raw timeout for this frame. (See FrameAnimator::GetTimeoutForFrame.)
   int32_t mTimeout; // -1 means display forever.
 
   DisposalMethod mDisposalMethod;
   BlendMethod    mBlendMethod;
+  Maybe<IntRect> mBlendRect;
   SurfaceFormat  mFormat;
 
   bool mHasNoAlpha;
   bool mAborted;
   bool mFinished;
   bool mOptimizable;
 
 
--- a/image/test/gtest/Common.cpp
+++ b/image/test/gtest/Common.cpp
@@ -18,16 +18,17 @@
 #include "nsString.h"
 
 namespace mozilla {
 namespace image {
 
 using namespace gfx;
 
 using std::abs;
+using std::vector;
 
 ///////////////////////////////////////////////////////////////////////////////
 // General Helpers
 ///////////////////////////////////////////////////////////////////////////////
 
 // These macros work like gtest's ASSERT_* macros, except that they can be used
 // in functions that return values.
 #define ASSERT_TRUE_OR_RETURN(e, rv) \
@@ -37,19 +38,31 @@ using std::abs;
   }
 
 #define ASSERT_EQ_OR_RETURN(a, b, rv) \
   EXPECT_EQ(a, b);                    \
   if ((a) != (b)) {                   \
     return rv;                        \
   }
 
+#define ASSERT_GE_OR_RETURN(a, b, rv) \
+  EXPECT_GE(a, b);                    \
+  if (!((a) >= (b))) {                \
+    return rv;                        \
+  }
+
 #define ASSERT_LE_OR_RETURN(a, b, rv) \
   EXPECT_LE(a, b);                    \
-  if (!((a) <= (b))) {                 \
+  if (!((a) <= (b))) {                \
+    return rv;                        \
+  }
+
+#define ASSERT_LT_OR_RETURN(a, b, rv) \
+  EXPECT_LT(a, b);                    \
+  if (!((a) < (b))) {                 \
     return rv;                        \
   }
 
 already_AddRefed<nsIInputStream>
 LoadFile(const char* aRelativePath)
 {
   nsresult rv;
 
@@ -200,16 +213,51 @@ PalettedRectIsSolidColor(Decoder* aDecod
       int32_t i = row * rowLength + col;
       ASSERT_EQ_OR_RETURN(aColor, imageData[i], false);
     }
   }
 
   return true;
 }
 
+bool
+RowHasPixels(SourceSurface* aSurface,
+             int32_t aRow,
+             const vector<BGRAColor>& aPixels)
+{
+  ASSERT_GE_OR_RETURN(aRow, 0, false);
+
+  IntSize surfaceSize = aSurface->GetSize();
+  ASSERT_EQ_OR_RETURN(aPixels.size(), size_t(surfaceSize.width), false);
+  ASSERT_LT_OR_RETURN(aRow, surfaceSize.height, false);
+
+  RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
+  ASSERT_TRUE_OR_RETURN(dataSurface, false);
+
+  ASSERT_EQ_OR_RETURN(dataSurface->Stride(), surfaceSize.width * 4, false);
+
+  DataSourceSurface::ScopedMap mapping(dataSurface,
+                                       DataSourceSurface::MapType::READ);
+  ASSERT_TRUE_OR_RETURN(mapping.IsMapped(), false);
+
+  uint8_t* data = dataSurface->GetData();
+  ASSERT_TRUE_OR_RETURN(data != nullptr, false);
+
+  int32_t rowLength = dataSurface->Stride();
+  for (int32_t col = 0; col < surfaceSize.width; ++col) {
+    int32_t i = aRow * rowLength + col * 4;
+    ASSERT_EQ_OR_RETURN(aPixels[col].mBlue,  data[i + 0], false);
+    ASSERT_EQ_OR_RETURN(aPixels[col].mGreen, data[i + 1], false);
+    ASSERT_EQ_OR_RETURN(aPixels[col].mRed,   data[i + 2], false);
+    ASSERT_EQ_OR_RETURN(aPixels[col].mAlpha, data[i + 3], false);
+  }
+
+  return true;
+}
+
 
 ///////////////////////////////////////////////////////////////////////////////
 // SurfacePipe Helpers
 ///////////////////////////////////////////////////////////////////////////////
 
 already_AddRefed<Decoder>
 CreateTrivialDecoder()
 {
--- a/image/test/gtest/Common.h
+++ b/image/test/gtest/Common.h
@@ -1,16 +1,18 @@
 /* -*- 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/. */
 
 #ifndef mozilla_image_test_gtest_Common_h
 #define mozilla_image_test_gtest_Common_h
 
+#include <vector>
+
 #include "gtest/gtest.h"
 
 #include "mozilla/Maybe.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/gfx/2D.h"
 #include "Decoder.h"
 #include "gfxColor.h"
 #include "nsCOMPtr.h"
@@ -65,25 +67,28 @@ struct ImageTestCase
   const char* mMimeType;
   gfx::IntSize mSize;
   gfx::IntSize mOutputSize;
   uint32_t mFlags;
 };
 
 struct BGRAColor
 {
+  BGRAColor() : BGRAColor(0, 0, 0, 0) { }
+
   BGRAColor(uint8_t aBlue, uint8_t aGreen, uint8_t aRed, uint8_t aAlpha)
     : mBlue(aBlue)
     , mGreen(aGreen)
     , mRed(aRed)
     , mAlpha(aAlpha)
   { }
 
   static BGRAColor Green() { return BGRAColor(0x00, 0xFF, 0x00, 0xFF); }
   static BGRAColor Red()   { return BGRAColor(0x00, 0x00, 0xFF, 0xFF); }
+  static BGRAColor Blue()   { return BGRAColor(0xFF, 0x00, 0x00, 0xFF); }
   static BGRAColor Transparent() { return BGRAColor(0x00, 0x00, 0x00, 0x00); }
 
   uint32_t AsPixel() const { return gfxPackedPixel(mAlpha, mRed, mGreen, mBlue); }
 
   uint8_t mBlue;
   uint8_t mGreen;
   uint8_t mRed;
   uint8_t mAlpha;
@@ -152,16 +157,24 @@ bool RectIsSolidColor(gfx::SourceSurface
 /**
  * @returns true if every pixel in the rect specified by @aRect has the palette
  * index specified by @aColor.
  */
 bool PalettedRectIsSolidColor(Decoder* aDecoder,
                               const gfx::IntRect& aRect,
                               uint8_t aColor);
 
+/**
+ * @returns true if the pixels in @aRow of @aSurface match the pixels given in
+ * @aPixels.
+ */
+bool RowHasPixels(gfx::SourceSurface* aSurface,
+                  int32_t aRow,
+                  const std::vector<BGRAColor>& aPixels);
+
 
 ///////////////////////////////////////////////////////////////////////////////
 // SurfacePipe Helpers
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
  * Creates a decoder with no data associated with, suitable for testing code
  * that requires a decoder to initialize or to allocate surfaces but doesn't
new file mode 100644
--- /dev/null
+++ b/image/test/gtest/TestADAM7InterpolatingFilter.cpp
@@ -0,0 +1,671 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#include <algorithm>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+#include "mozilla/gfx/2D.h"
+#include "mozilla/Maybe.h"
+#include "Common.h"
+#include "Decoder.h"
+#include "DecoderFactory.h"
+#include "SourceBuffer.h"
+#include "SurfaceFilters.h"
+#include "SurfacePipe.h"
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+using namespace mozilla::image;
+
+using std::generate;
+using std::vector;
+
+template <typename Func> void
+WithADAM7InterpolatingFilter(const IntSize& aSize, Func aFunc)
+{
+  RefPtr<Decoder> decoder = CreateTrivialDecoder();
+  ASSERT_TRUE(bool(decoder));
+
+  WithFilterPipeline(decoder, Forward<Func>(aFunc),
+                     ADAM7InterpolatingConfig { },
+                     SurfaceConfig { decoder, 0, aSize,
+                                     SurfaceFormat::B8G8R8A8, false });
+}
+
+void
+AssertConfiguringADAM7InterpolatingFilterFails(const IntSize& aSize)
+{
+  RefPtr<Decoder> decoder = CreateTrivialDecoder();
+  ASSERT_TRUE(bool(decoder));
+
+  AssertConfiguringPipelineFails(decoder,
+                                 ADAM7InterpolatingConfig { },
+                                 SurfaceConfig { decoder, 0, aSize,
+                                                 SurfaceFormat::B8G8R8A8, false });
+}
+
+uint8_t
+InterpolateByte(uint8_t aByteA, uint8_t aByteB, float aWeight)
+{
+  return uint8_t(aByteA * aWeight + aByteB * (1.0f - aWeight));
+}
+
+BGRAColor
+InterpolateColors(BGRAColor aColor1, BGRAColor aColor2, float aWeight)
+{
+  return BGRAColor(InterpolateByte(aColor1.mBlue,  aColor2.mBlue,  aWeight),
+                   InterpolateByte(aColor1.mGreen, aColor2.mGreen, aWeight),
+                   InterpolateByte(aColor1.mRed,   aColor2.mRed,   aWeight),
+                   InterpolateByte(aColor1.mAlpha, aColor2.mAlpha, aWeight));
+}
+
+enum class ShouldInterpolate
+{
+  eYes,
+  eNo
+};
+
+BGRAColor
+HorizontallyInterpolatedPixel(uint32_t aCol,
+                              uint32_t aWidth,
+                              const vector<float>& aWeights,
+                              ShouldInterpolate aShouldInterpolate,
+                              const vector<BGRAColor>& aColors)
+{
+  // We cycle through the vector of weights forever.
+  float weight = aWeights[aCol % aWeights.size()];
+
+  // Find the columns of the two final pixels for this set of weights.
+  uint32_t finalPixel1 = aCol - aCol % aWeights.size();
+  uint32_t finalPixel2 = finalPixel1 + aWeights.size();
+
+  // If |finalPixel2| is past the end of the row, that means that there is no
+  // final pixel after the pixel at |finalPixel1|. In that case, we just want to
+  // duplicate |finalPixel1|'s color until the end of the row. We can do that by
+  // setting |finalPixel2| equal to |finalPixel1| so that the interpolation has
+  // no effect.
+  if (finalPixel2 >= aWidth) {
+    finalPixel2 = finalPixel1;
+  }
+
+  // We cycle through the vector of colors forever (subject to the above
+  // constraint about the end of the row).
+  BGRAColor color1 = aColors[finalPixel1 % aColors.size()];
+  BGRAColor color2 = aColors[finalPixel2 % aColors.size()];
+
+  // If we're not interpolating, we treat all pixels which aren't final as
+  // transparent. Since the number of weights we have is equal to the stride
+  // between final pixels, we can check if |aCol| is a final pixel by checking
+  // whether |aCol| is a multiple of |aWeights.size()|.
+  if (aShouldInterpolate == ShouldInterpolate::eNo) {
+    return aCol % aWeights.size() == 0 ? color1
+                                       : BGRAColor::Transparent();
+  }
+
+  // Interpolate.
+  return InterpolateColors(color1, color2, weight);
+}
+
+vector<float>&
+InterpolationWeights(int32_t aStride)
+{
+  // Precalculated interpolation weights. These are used to interpolate
+  // between final pixels or between important rows. Although no interpolation
+  // is actually applied to the previous final pixel or important row value,
+  // the arrays still start with 1.0f, which is always skipped, primarily
+  // because otherwise |stride1Weights| would have zero elements.
+  static vector<float> stride8Weights =
+    { 1.0f, 7 / 8.0f, 6 / 8.0f, 5 / 8.0f, 4 / 8.0f, 3 / 8.0f, 2 / 8.0f, 1 / 8.0f };
+  static vector<float> stride4Weights = { 1.0f, 3 / 4.0f, 2 / 4.0f, 1 / 4.0f };
+  static vector<float> stride2Weights = { 1.0f, 1 / 2.0f };
+  static vector<float> stride1Weights = { 1.0f };
+
+  switch (aStride) {
+    case 8: return stride8Weights;
+    case 4: return stride4Weights;
+    case 2: return stride2Weights;
+    case 1: return stride1Weights;
+    default:
+      MOZ_CRASH();
+  }
+}
+
+int32_t
+ImportantRowStride(uint8_t aPass)
+{
+  // The stride between important rows for each pass, with a dummy value for
+  // the nonexistent pass 0 and for pass 8, since the tests run an extra pass to
+  // make sure nothing breaks.
+  static int32_t strides[] = { 1, 8, 8, 4, 4, 2, 2, 1, 1 };
+
+  return strides[aPass];
+}
+
+size_t
+FinalPixelStride(uint8_t aPass)
+{
+  // The stride between the final pixels in important rows for each pass, with
+  // a dummy value for the nonexistent pass 0 and for pass 8, since the tests
+  // run an extra pass to make sure nothing breaks.
+  static size_t strides[] = { 1, 8, 4, 4, 2, 2, 1, 1, 1 };
+
+  return strides[aPass];
+}
+
+bool
+IsImportantRow(int32_t aRow, uint8_t aPass)
+{
+  return aRow % ImportantRowStride(aPass) == 0;
+}
+
+/**
+ * ADAM7 breaks up the image into 8x8 blocks. On each of the 7 passes, a new
+ * set of pixels in each block receives their final values, according to the
+ * following pattern:
+ *
+ *    1 6 4 6 2 6 4 6
+ *    7 7 7 7 7 7 7 7
+ *    5 6 5 6 5 6 5 6
+ *    7 7 7 7 7 7 7 7
+ *    3 6 4 6 3 6 4 6
+ *    7 7 7 7 7 7 7 7
+ *    5 6 5 6 5 6 5 6
+ *    7 7 7 7 7 7 7 7
+ *
+ * This function produces a row of pixels @aWidth wide, suitable for testing
+ * horizontal interpolation on pass @aPass. The pattern of pixels used is
+ * determined by @aPass and @aRow, which determine which pixels are final
+ * according to the table above, and @aColors, from which the pixel values
+ * are selected.
+ *
+ * There are two different behaviors: if |eNo| is passed for
+ * @aShouldInterpolate, non-final pixels are treated as transparent. If |eNo|
+ * is passed, non-final pixels get interpolated in from the surrounding final
+ * pixels. The intention is that |eNo| is passed to generate input which will
+ * be run through ADAM7InterpolatingFilter, and |eYes| is passed to generate
+ * reference data to check that the filter is performing horizontal
+ * interpolation correctly.
+ *
+ * This function does not perform vertical interpolation. Rows which aren't on
+ * the current pass are filled with transparent pixels.
+ *
+ * @return a vector<BGRAColor> representing a row of pixels.
+ */
+vector<BGRAColor>
+ADAM7HorizontallyInterpolatedRow(uint8_t aPass,
+                                 uint32_t aRow,
+                                 uint32_t aWidth,
+                                 ShouldInterpolate aShouldInterpolate,
+                                 const vector<BGRAColor>& aColors)
+{
+  EXPECT_GT(aPass, 0);
+  EXPECT_LE(aPass, 8);
+  EXPECT_GT(aColors.size(), 0u);
+
+  vector<BGRAColor> result(aWidth);
+
+  if (IsImportantRow(aRow, aPass)) {
+    vector<float>& weights = InterpolationWeights(FinalPixelStride(aPass));
+
+    // Compute the horizontally interpolated row.
+    uint32_t col = 0;
+    generate(result.begin(), result.end(), [&]{
+      return HorizontallyInterpolatedPixel(col++, aWidth, weights,
+                                           aShouldInterpolate, aColors);
+    });
+  } else {
+    // This is an unimportant row; just make the entire thing transparent.
+    generate(result.begin(), result.end(), []{
+      return BGRAColor::Transparent();
+    });
+  }
+
+  EXPECT_EQ(result.size(), size_t(aWidth));
+
+  return result;
+}
+
+WriteState
+WriteUninterpolatedPixels(SurfaceFilter* aFilter,
+                          const IntSize& aSize,
+                          uint8_t aPass,
+                          const vector<BGRAColor>& aColors)
+{
+  WriteState result = WriteState::NEED_MORE_DATA;
+
+  for (int32_t row = 0; row < aSize.height; ++row) {
+    // Compute uninterpolated pixels for this row.
+    vector<BGRAColor> pixels =
+      Move(ADAM7HorizontallyInterpolatedRow(aPass, row, aSize.width,
+                                            ShouldInterpolate::eNo, aColors));
+
+    // Write them to the surface.
+    auto pixelIterator = pixels.cbegin();
+    result = aFilter->WritePixelsToRow<uint32_t>([&]{
+      return AsVariant((*pixelIterator++).AsPixel());
+    });
+
+    if (result != WriteState::NEED_MORE_DATA) {
+      break;
+    }
+  }
+
+  return result;
+}
+
+bool
+CheckHorizontallyInterpolatedImage(Decoder* aDecoder,
+                                   const IntSize& aSize,
+                                   uint8_t aPass,
+                                   const vector<BGRAColor>& aColors)
+{
+  RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
+  RefPtr<SourceSurface> surface = currentFrame->GetSurface();
+
+  for (int32_t row = 0; row < aSize.height; ++row) {
+    if (!IsImportantRow(row, aPass)) {
+      continue;  // Don't check rows which aren't important on this pass.
+    }
+
+    // Compute the expected pixels, *with* interpolation to match what the
+    // filter should have done.
+    vector<BGRAColor> expectedPixels =
+      Move(ADAM7HorizontallyInterpolatedRow(aPass, row, aSize.width,
+                                            ShouldInterpolate::eYes, aColors));
+
+    if (!RowHasPixels(surface, row, expectedPixels)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void
+CheckHorizontalInterpolation(const IntSize& aSize,
+                             const vector<BGRAColor>& aColors)
+{
+  const IntRect surfaceRect(IntPoint(0, 0), aSize);
+
+  WithADAM7InterpolatingFilter(aSize,
+                               [&](Decoder* aDecoder, SurfaceFilter* aFilter) {
+    // We check horizontal interpolation behavior for each pass individually. In
+    // addition to the normal 7 passes that ADAM7 includes, we also check an
+    // eighth pass to verify that nothing breaks if extra data is written.
+    for (uint8_t pass = 1; pass <= 8; ++pass) {
+      // Write our color pattern to the surface. We don't perform any
+      // interpolation when writing to the filter so that we can check that the
+      // filter itself *does*.
+      WriteState result =
+        WriteUninterpolatedPixels(aFilter, aSize, pass, aColors);
+
+      EXPECT_EQ(WriteState::FINISHED, result);
+      AssertCorrectPipelineFinalState(aFilter, surfaceRect, surfaceRect);
+
+      // Check that the generated image matches the expected pattern, with
+      // interpolation applied.
+      EXPECT_TRUE(CheckHorizontallyInterpolatedImage(aDecoder, aSize,
+                                                     pass, aColors));
+
+      // Prepare for the next pass.
+      aFilter->ResetToFirstRow();
+    }
+  });
+}
+
+BGRAColor
+ADAM7RowColor(int32_t aRow,
+              uint8_t aPass,
+              const vector<BGRAColor>& aColors)
+{
+  EXPECT_LT(0, aPass);
+  EXPECT_GE(8, aPass);
+  EXPECT_LT(0u, aColors.size());
+
+  // If this is an important row, select the color from the provided vector of
+  // colors, which we cycle through infinitely. If not, just fill the row with
+  // transparent pixels.
+  return IsImportantRow(aRow, aPass) ? aColors[aRow % aColors.size()]
+                                     : BGRAColor::Transparent();
+}
+
+WriteState
+WriteRowColorPixels(SurfaceFilter* aFilter,
+                    const IntSize& aSize,
+                    uint8_t aPass,
+                    const vector<BGRAColor>& aColors)
+{
+  WriteState result = WriteState::NEED_MORE_DATA;
+
+  for (int32_t row = 0; row < aSize.height; ++row) {
+    const uint32_t color = ADAM7RowColor(row, aPass, aColors).AsPixel();
+
+    // Fill the surface with |color| pixels.
+    result = aFilter->WritePixelsToRow<uint32_t>([&]{ return AsVariant(color); });
+
+    if (result != WriteState::NEED_MORE_DATA) {
+      break;
+    }
+  }
+
+  return result;
+}
+
+bool
+CheckVerticallyInterpolatedImage(Decoder* aDecoder,
+                                 const IntSize& aSize,
+                                 uint8_t aPass,
+                                 const vector<BGRAColor>& aColors)
+{
+  vector<float>& weights = InterpolationWeights(ImportantRowStride(aPass));
+
+  for (int32_t row = 0; row < aSize.height; ++row) {
+    // Vertically interpolation takes place between two important rows. The
+    // separation between the important rows is determined by the stride of this
+    // pass. When there is no "next" important row because we'd run off the
+    // bottom of the image, we use the same row for both. This matches
+    // ADAM7InterpolatingFilter's behavior of duplicating the last important row
+    // since there isn't another important row to vertically interpolate it
+    // with.
+    const int32_t stride = ImportantRowStride(aPass);
+    const int32_t prevImportantRow = row - row % stride;
+    const int32_t maybeNextImportantRow = prevImportantRow + stride;
+    const int32_t nextImportantRow = maybeNextImportantRow < aSize.height
+                                   ? maybeNextImportantRow
+                                   : prevImportantRow;
+
+    // Retrieve the colors for the important rows we're going to interpolate.
+    const BGRAColor prevImportantRowColor =
+      ADAM7RowColor(prevImportantRow, aPass, aColors);
+    const BGRAColor nextImportantRowColor =
+      ADAM7RowColor(nextImportantRow, aPass, aColors);
+
+    // The weight we'll use for interpolation is also determined by the stride.
+    // A row halfway between two important rows should have pixels that have a
+    // 50% contribution from each of the important rows, for example.
+    const float weight = weights[row % stride];
+    const BGRAColor interpolatedColor =
+      InterpolateColors(prevImportantRowColor, nextImportantRowColor, weight);
+
+    // Generate a row of expected pixels. Every pixel in the row is always the
+    // same color since we're only testing vertical interpolation between
+    // solid-colored rows.
+    vector<BGRAColor> expectedPixels(aSize.width);
+    generate(expectedPixels.begin(), expectedPixels.end(), [&]{
+      return interpolatedColor;
+    });
+
+    // Check that the pixels match.
+    RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
+    RefPtr<SourceSurface> surface = currentFrame->GetSurface();
+    if (!RowHasPixels(surface, row, expectedPixels)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void
+CheckVerticalInterpolation(const IntSize& aSize,
+                           const vector<BGRAColor>& aColors)
+{
+  const IntRect surfaceRect(IntPoint(0, 0), aSize);
+
+  WithADAM7InterpolatingFilter(aSize,
+                               [&](Decoder* aDecoder, SurfaceFilter* aFilter) {
+    for (uint8_t pass = 1; pass <= 8; ++pass) {
+      // Write a pattern of rows to the surface. Important rows will receive a
+      // color selected from |aColors|; unimportant rows will be transparent.
+      WriteState result = WriteRowColorPixels(aFilter, aSize, pass, aColors);
+
+      EXPECT_EQ(WriteState::FINISHED, result);
+      AssertCorrectPipelineFinalState(aFilter, surfaceRect, surfaceRect);
+
+      // Check that the generated image matches the expected pattern, with
+      // interpolation applied.
+      EXPECT_TRUE(CheckVerticallyInterpolatedImage(aDecoder, aSize,
+                                                   pass, aColors));
+
+      // Prepare for the next pass.
+      aFilter->ResetToFirstRow();
+    }
+  });
+}
+
+void
+CheckInterpolation(const IntSize& aSize, const vector<BGRAColor>& aColors)
+{
+  CheckHorizontalInterpolation(aSize, aColors);
+  CheckVerticalInterpolation(aSize, aColors);
+}
+
+void
+CheckADAM7InterpolatingWritePixels(const IntSize& aSize)
+{
+  // This test writes 8 passes of green pixels (the seven ADAM7 passes, plus one
+  // extra to make sure nothing goes wrong if we write too much input) and verifies
+  // that the output is a solid green surface each time. Because all the pixels
+  // are the same color, interpolation doesn't matter; we test the correctness
+  // of the interpolation algorithm itself separately.
+  WithADAM7InterpolatingFilter(aSize,
+                               [&](Decoder* aDecoder, SurfaceFilter* aFilter) {
+    IntRect rect(IntPoint(0, 0), aSize);
+
+    for (int32_t pass = 1; pass <= 8; ++pass) {
+      // We only actually write up to the last important row for each pass,
+      // because that row unambiguously determines the remaining rows.
+      const int32_t lastRow = aSize.height - 1;
+      const int32_t lastImportantRow =
+        lastRow - (lastRow % ImportantRowStride(pass));
+      const IntRect inputWriteRect(0, 0, aSize.width, lastImportantRow + 1);
+
+      CheckWritePixels(aDecoder, aFilter,
+                       /* aOutputRect = */ Some(rect),
+                       /* aInputRect = */ Some(rect),
+                       /* aInputWriteRect = */ Some(inputWriteRect));
+
+      aFilter->ResetToFirstRow();
+      EXPECT_FALSE(aFilter->IsSurfaceFinished());
+      Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
+      EXPECT_TRUE(invalidRect.isNothing());
+    }
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels100_100)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(100, 100));
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels99_99)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(99, 99));
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels66_33)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(66, 33));
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels33_66)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(33, 66));
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels15_15)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(15, 15));
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels9_9)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(9, 9));
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels8_8)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(8, 8));
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels7_7)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(7, 7));
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels3_3)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(3, 3));
+}
+
+TEST(ImageADAM7InterpolatingFilter, WritePixels1_1)
+{
+  CheckADAM7InterpolatingWritePixels(IntSize(1, 1));
+}
+
+TEST(ImageADAM7InterpolatingFilter, TrivialInterpolation48_48)
+{
+  CheckInterpolation(IntSize(48, 48), { BGRAColor::Green() });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput33_17)
+{
+  // We check interpolation using irregular patterns to make sure that the
+  // interpolation will look different for different passes.
+  CheckInterpolation(IntSize(33, 17), {
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),
+    BGRAColor::Blue(),  BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Green(),
+    BGRAColor::Red(),   BGRAColor::Red(),   BGRAColor::Blue(),  BGRAColor::Blue(),
+    BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Blue(),
+    BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Red(),   BGRAColor::Blue(),
+    BGRAColor::Blue(),  BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Green(),
+    BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Blue()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput32_16)
+{
+  CheckInterpolation(IntSize(32, 16), {
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),
+    BGRAColor::Blue(),  BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Green(),
+    BGRAColor::Red(),   BGRAColor::Red(),   BGRAColor::Blue(),  BGRAColor::Blue(),
+    BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Blue(),
+    BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Red(),   BGRAColor::Blue(),
+    BGRAColor::Blue(),  BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Green(),
+    BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Blue()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput31_15)
+{
+  CheckInterpolation(IntSize(31, 15), {
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),
+    BGRAColor::Blue(),  BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Green(),
+    BGRAColor::Red(),   BGRAColor::Red(),   BGRAColor::Blue(),  BGRAColor::Blue(),
+    BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Blue(),
+    BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Red(),   BGRAColor::Blue(),
+    BGRAColor::Blue(),  BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Green(),
+    BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Blue()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput17_33)
+{
+  CheckInterpolation(IntSize(17, 33), {
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),
+    BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),
+    BGRAColor::Blue(),  BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Green(),
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Red(),   BGRAColor::Blue()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput16_32)
+{
+  CheckInterpolation(IntSize(16, 32), {
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),
+    BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),
+    BGRAColor::Blue(),  BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Green(),
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Red(),   BGRAColor::Blue()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput15_31)
+{
+  CheckInterpolation(IntSize(15, 31), {
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),
+    BGRAColor::Red(),   BGRAColor::Green(), BGRAColor::Blue(),  BGRAColor::Red(),
+    BGRAColor::Blue(),  BGRAColor::Blue(),  BGRAColor::Red(),   BGRAColor::Green(),
+    BGRAColor::Green(), BGRAColor::Red(),   BGRAColor::Red(),   BGRAColor::Blue()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput9_9)
+{
+  CheckInterpolation(IntSize(9, 9), {
+    BGRAColor::Blue(),  BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(),
+    BGRAColor::Green(), BGRAColor::Red(),  BGRAColor::Red(), BGRAColor::Blue()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput8_8)
+{
+  CheckInterpolation(IntSize(8, 8), {
+    BGRAColor::Blue(),  BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(),
+    BGRAColor::Green(), BGRAColor::Red(),  BGRAColor::Red(), BGRAColor::Blue()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput7_7)
+{
+  CheckInterpolation(IntSize(7, 7), {
+    BGRAColor::Blue(),  BGRAColor::Blue(), BGRAColor::Red(), BGRAColor::Green(),
+    BGRAColor::Green(), BGRAColor::Red(),  BGRAColor::Red(), BGRAColor::Blue()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput3_3)
+{
+  CheckInterpolation(IntSize(3, 3), {
+    BGRAColor::Green(), BGRAColor::Red(), BGRAColor::Blue(), BGRAColor::Red()
+  });
+}
+
+TEST(ImageADAM7InterpolatingFilter, InterpolationOutput1_1)
+{
+  CheckInterpolation(IntSize(1, 1), { BGRAColor::Blue() });
+}
+
+TEST(ImageADAM7InterpolatingFilter, ADAM7InterpolationFailsFor0_0)
+{
+  // A 0x0 input size is invalid, so configuration should fail.
+  AssertConfiguringADAM7InterpolatingFilterFails(IntSize(0, 0));
+}
+
+TEST(ImageADAM7InterpolatingFilter, ADAM7InterpolationFailsForMinus1_Minus1)
+{
+  // A negative input size is invalid, so configuration should fail.
+  AssertConfiguringADAM7InterpolatingFilterFails(IntSize(-1, -1));
+}
+
+TEST(ImageADAM7InterpolatingFilter, ConfiguringPalettedADAM7InterpolatingFilterFails)
+{
+  RefPtr<Decoder> decoder = CreateTrivialDecoder();
+  ASSERT_TRUE(decoder != nullptr);
+
+  // ADAM7InterpolatingFilter does not support paletted images, so configuration
+  // should fail.
+  AssertConfiguringPipelineFails(decoder,
+                                 ADAM7InterpolatingConfig { },
+                                 PalettedSurfaceConfig { decoder, 0, IntSize(100, 100),
+                                                         IntRect(0, 0, 50, 50),
+                                                         SurfaceFormat::B8G8R8A8, 8,
+                                                         false });
+}
--- a/image/test/gtest/moz.build
+++ b/image/test/gtest/moz.build
@@ -3,16 +3,17 @@
 # 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/.
 
 Library('imagetest')
 
 UNIFIED_SOURCES = [
     'Common.cpp',
+    'TestADAM7InterpolatingFilter.cpp',
     'TestCopyOnWrite.cpp',
     'TestDecoders.cpp',
     'TestDecodeToSurface.cpp',
     'TestDeinterlacingFilter.cpp',
     'TestMetadata.cpp',
     'TestRemoveFrameRectFilter.cpp',
     'TestStreamingLexer.cpp',
     'TestSurfaceSink.cpp',
--- a/js/src/tests/ecma_6/Function/has-instance.js
+++ b/js/src/tests/ecma_6/Function/has-instance.js
@@ -76,13 +76,26 @@ let xOuter = bindme.x;
 let bound = xOuter.bind(bindme);
 let doubleBound = bound.bind(bindme);
 let tripleBound = bound.bind(doubleBound);
 assertEq(Function.prototype[Symbol.hasInstance].call(bound, instance), true);
 assertEq(Function.prototype[Symbol.hasInstance].call(doubleBound, instance), true);
 assertEq(Function.prototype[Symbol.hasInstance].call(tripleBound, instance), true);
 
 // Function.prototype[Symbol.hasInstance] is not configurable
-let desc = Object.getOwnPropertyDescriptor(Function.prototype, Symbol.hasInstance)
-assertEq(desc.configurable, false)
+let desc = Object.getOwnPropertyDescriptor(Function.prototype, Symbol.hasInstance);
+assertEq(desc.configurable, false);
+
+// Attempting to use a non-callable @@hasInstance triggers a type error
+// Bug 1280892
+assertThrowsInstanceOf(() => {
+    var fun = function() {}
+    var p = new Proxy(fun, {
+        get(target, key) {
+            return /not-callable/;
+        }
+    });
+    fun instanceof p;
+}, TypeError);
+
 
 if (typeof reportCompare === "function")
     reportCompare(true, true);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -720,31 +720,30 @@ js::InstanceOfOperator(JSContext* cx, Ha
     /* Step 2. */
     RootedValue hasInstance(cx);
     RootedId id(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().hasInstance));
     if (!GetProperty(cx, obj, obj, id, &hasInstance))
         return false;
 
     if (!hasInstance.isNullOrUndefined()) {
         if (!IsCallable(hasInstance))
-            ReportIsNotFunction(cx, hasInstance);
+            return ReportIsNotFunction(cx, hasInstance);
 
         /* Step 3. */
         RootedValue rval(cx);
         if (!Call(cx, hasInstance, obj, v, &rval))
             return false;
         *bp = ToBoolean(rval);
         return true;
     }
 
     /* Step 4. */
     if (!obj->isCallable()) {
         RootedValue val(cx, ObjectValue(*obj));
-        ReportIsNotFunction(cx, val);
-        return false;
+        return ReportIsNotFunction(cx, val);
     }
 
     /* Step 5. */
     return js::OrdinaryHasInstance(cx, obj, v, bp);
 }
 
 bool
 js::HasInstance(JSContext* cx, HandleObject obj, HandleValue v, bool* bp)
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/1278455-1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html style="transform: translateX(3px); display: grid;">
+<head>
+<!--
+user_pref("layout.event-regions.enabled", true);
+-->
+</head>
+<body>
+<div style="position: absolute;">Z</div>
+</body>
+</html>
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -468,8 +468,9 @@ load 1127198-1.html
 load 1140198.html
 pref(layout.css.grid.enabled,true) load 1156588.html
 load 1162813.xul
 load 1163583.html
 load 1234622-1.html
 load 1235467-1.html
 pref(dom.webcomponents.enabled,true) load 1261351.html
 load 1270797-1.html
+load 1278455-1.html
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -2491,40 +2491,42 @@ nsCSSFrameConstructor::ConstructDocEleme
   }
 
   TreeMatchContext::AutoAncestorPusher ancestorPusher(state.mTreeMatchContext);
   ancestorPusher.PushAncestorAndStyleScope(aDocElement);
 
   // Make sure to start any background image loads for the root element now.
   styleContext->StartBackgroundImageLoads();
 
-  nsFrameConstructorSaveState absoluteSaveState;
+  nsFrameConstructorSaveState docElementContainingBlockAbsoluteSaveState;
   if (mHasRootAbsPosContainingBlock) {
     // Push the absolute containing block now so we can absolutely position
     // the root element
     mDocElementContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
     state.PushAbsoluteContainingBlock(mDocElementContainingBlock,
                                       mDocElementContainingBlock,
-                                      absoluteSaveState);
+                                      docElementContainingBlockAbsoluteSaveState);
   }
 
   // The rules from CSS 2.1, section 9.2.4, have already been applied
   // by the style system, so we can assume that display->mDisplay is
   // either NONE, BLOCK, or TABLE.
 
   // contentFrame is the primary frame for the root element. newFrame
   // is the frame that will be the child of the initial containing block.
   // These are usually the same frame but they can be different, in
   // particular if the root frame is positioned, in which case
   // contentFrame is the out-of-flow frame and newFrame is the
   // placeholder.
   nsContainerFrame* contentFrame;
   nsIFrame* newFrame;
   bool processChildren = false;
 
+  nsFrameConstructorSaveState absoluteSaveState;
+
   // Check whether we need to build a XUL box or SVG root frame
 #ifdef MOZ_XUL
   if (aDocElement->IsXULElement()) {
     contentFrame = NS_NewDocElementBoxFrame(mPresShell, styleContext);
     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
                         contentFrame);
     newFrame = contentFrame;
     processChildren = true;
@@ -2560,22 +2562,36 @@ nsCSSFrameConstructor::ConstructDocEleme
     NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
   } else if (display->mDisplay == NS_STYLE_DISPLAY_FLEX ||
              display->mDisplay == NS_STYLE_DISPLAY_WEBKIT_BOX) {
     contentFrame = NS_NewFlexContainerFrame(mPresShell, styleContext);
     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
                         contentFrame);
     newFrame = contentFrame;
     processChildren = true;
+
+    newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
+    if (display->IsAbsPosContainingBlock(newFrame)) {
+      state.PushAbsoluteContainingBlock(contentFrame, newFrame,
+                                        absoluteSaveState);
+    }
+
   } else if (display->mDisplay == NS_STYLE_DISPLAY_GRID) {
     contentFrame = NS_NewGridContainerFrame(mPresShell, styleContext);
     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
                         contentFrame);
     newFrame = contentFrame;
     processChildren = true;
+
+    newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
+    if (display->IsAbsPosContainingBlock(newFrame)) {
+      state.PushAbsoluteContainingBlock(contentFrame, newFrame,
+                                        absoluteSaveState);
+    }
+
   } else if (display->mDisplay == NS_STYLE_DISPLAY_TABLE) {
     // We're going to call the right function ourselves, so no need to give a
     // function to this FrameConstructionData.
 
     // XXXbz on the other hand, if we converted this whole function to
     // FrameConstructionData/Item, then we'd need the right function
     // here... but would probably be able to get away with less code in this
     // function in general.
--- a/layout/style/nsCSSDataBlock.cpp
+++ b/layout/style/nsCSSDataBlock.cpp
@@ -66,20 +66,22 @@ TryToStartImageLoadOnValue(const nsCSSVa
     // 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();
       nsIURI* imageURI = aValue.GetURLValue();
-      bool isEqualExceptRef = false;
-      nsresult  rv = imageURI->EqualsExceptRef(docURI, &isEqualExceptRef);
-      if (NS_SUCCEEDED(rv) && isEqualExceptRef) {
-        return;
+      if (imageURI) {
+        bool isEqualExceptRef = false;
+        nsresult  rv = imageURI->EqualsExceptRef(docURI, &isEqualExceptRef);
+        if (NS_SUCCEEDED(rv) && isEqualExceptRef) {
+          return;
+        }
       }
     }
 #endif
     aValue.StartImageLoad(aDocument);
     if (aForTokenStream && aContext) {
       CSSVariableImageTable::Add(aContext, aProperty,
                                  aValue.GetImageStructValue());
     }
--- a/layout/style/test/test_restyles_in_smil_animation.html
+++ b/layout/style/test/test_restyles_in_smil_animation.html
@@ -4,16 +4,22 @@
 <title>Tests restyles in smil animation</title>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
 <script src="/tests/SimpleTest/SpawnTask.js"></script>
 <script src="/tests/SimpleTest/paint_listener.js"></script>
 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
 </head>
 <body>
 
+<div id="target-div">
+  <svg>
+    <rect id="svg-rect" width="100%" height="100%" fill="lime"/>
+  </svg>
+</div>
+
 <script>
 "use strict";
 
 function waitForAnimationFrames(frameCount) {
   return new Promise(function(resolve, reject) {
     function handleFrame() {
       if (--frameCount <= 0) {
         resolve();
@@ -55,55 +61,43 @@ function ensureElementRemoval(aElement) 
 }
 
 function waitForPaintFlushed() {
   return new Promise(function(resolve) {
     waitForAllPaintsFlushed(resolve);
   });
 }
 
-function addTestElement() {
-  var div = document.createElement("div");
-  var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
-  div.appendChild(svg);
+SimpleTest.waitForExplicitFinish();
 
-  var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
-  rect.setAttribute("width", "100%");
-  rect.setAttribute("height", "100%");
-  rect.setAttribute("fill", "lime");
-  svg.appendChild(rect);
+add_task(function* smil_is_in_display_none_subtree() {
+  yield waitForPaintFlushed();
 
   var animate =
     document.createElementNS("http://www.w3.org/2000/svg", "animate");
   animate.setAttribute("attributeType", "XML");
   animate.setAttribute("attributeName", "fill");
   animate.setAttribute("values", "red;lime");
   animate.setAttribute("dur", "1s");
   animate.setAttribute("repeatCount", "indefinite");
-  rect.appendChild(animate);
+  document.getElementById("svg-rect").appendChild(animate);
 
-  document.body.appendChild(div);
-  return div;
-}
-
-SimpleTest.waitForExplicitFinish();
-
-add_task(function* smil_is_in_display_none_subtree() {
-  var div = addTestElement();
   yield waitForPaintFlushed();
 
   var displayMarkers = yield observeStyling(5);
   is(displayMarkers.length, 5, "should restyle in every frame");
 
+  var div = document.getElementById("target-div");
+
   div.style.display = "none";
   getComputedStyle(div).display;
   var displayNoneMarkers = yield observeStyling(5);
   is(displayNoneMarkers.length, 0, "should never restyle if display:none");
 
   div.style.display = "";
   getComputedStyle(div).display;
   var displayAgainMarkers = yield observeStyling(5);
   is(displayAgainMarkers.length, 5, "should restyle again");
 
-  yield ensureElementRemoval(div);
+  yield ensureElementRemoval(animate);
 });
 </script>
 </body>
--- a/media/libjpeg/1050342.diff
+++ b/media/libjpeg/1050342.diff
@@ -1,53 +1,54 @@
 Bug 1050342. Fix a case where the fast huffman decoder in libjpeg-turbo can produce different results depending on how data is fed to it.
 
 This change comes from the blink repo https://codereview.appspot.com/229430043/ and is unlikely to be accepted upstream into libjpeg-turbo.
 
 diff --git jdhuff.c jdhuff.c
 --- jdhuff.c
 +++ jdhuff.c
-@@ -661,34 +661,34 @@ decode_mcu_fast (j_decompress_ptr cinfo,
+@@ -664,17 +664,17 @@ decode_mcu_fast (j_decompress_ptr cinfo,
    ASSIGN_STATE(state, entropy->saved);
  
    for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
-     JBLOCKROW block = MCU_data[blkn];
-     d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
-     d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
+     JBLOCKROW block = MCU_data ? MCU_data[blkn] : NULL;
+     d_derived_tbl *dctbl = entropy->dc_cur_tbls[blkn];
+     d_derived_tbl *actbl = entropy->ac_cur_tbls[blkn];
      register int s, k, r, l;
  
 -    HUFF_DECODE_FAST(s, l, dctbl);
 +    HUFF_DECODE_FAST(s, l, dctbl, slow_decode_mcu);
      if (s) {
        FILL_BIT_BUFFER_FAST
        r = GET_BITS(s);
        s = HUFF_EXTEND(r, s);
      }
  
      if (entropy->dc_needed[blkn]) {
        int ci = cinfo->MCU_membership[blkn];
-       s += state.last_dc_val[ci];
+@@ -682,17 +682,17 @@ decode_mcu_fast (j_decompress_ptr cinfo,
        state.last_dc_val[ci] = s;
-       (*block)[0] = (JCOEF) s;
+       if (block)
+         (*block)[0] = (JCOEF) s;
      }
  
-     if (entropy->ac_needed[blkn]) {
+     if (entropy->ac_needed[blkn] && block) {
  
        for (k = 1; k < DCTSIZE2; k++) {
 -        HUFF_DECODE_FAST(s, l, actbl);
 +        HUFF_DECODE_FAST(s, l, actbl, slow_decode_mcu);
          r = s >> 4;
          s &= 15;
  
          if (s) {
            k += r;
            FILL_BIT_BUFFER_FAST
            r = GET_BITS(s);
            s = HUFF_EXTEND(r, s);
-@@ -697,33 +697,34 @@ decode_mcu_fast (j_decompress_ptr cinfo,
+@@ -701,33 +701,34 @@ decode_mcu_fast (j_decompress_ptr cinfo,
            if (r != 15) break;
            k += 15;
          }
        }
  
      } else {
  
        for (k = 1; k < DCTSIZE2; k++) {
@@ -76,17 +77,17 @@ diff --git jdhuff.c jdhuff.c
  
    br_state.bytes_in_buffer -= (buffer - br_state.next_input_byte);
    br_state.next_input_byte = buffer;
    BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
    ASSIGN_STATE(entropy->saved, state);
 diff --git jdhuff.h jdhuff.h
 --- jdhuff.h
 +++ jdhuff.h
-@@ -200,32 +200,34 @@ EXTERN(boolean) jpeg_fill_bit_buffer
+@@ -203,32 +203,34 @@ EXTERN(boolean) jpeg_fill_bit_buffer
    } else { \
  slowlabel: \
      if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
          { failaction; } \
      get_buffer = state.get_buffer; bits_left = state.bits_left; \
    } \
  }
  
@@ -111,10 +112,10 @@ diff --git jdhuff.h jdhuff.h
 -    s = htbl->pub->huffval[ (int) (s + htbl->valoffset[nb]) & 0xFF ]; \
 +    if (nb > 16) \
 +      goto slowlabel; \
 +    s = htbl->pub->huffval[ (int) (s + htbl->valoffset[nb]) ]; \
    }
  
  /* Out-of-line case for Huffman code fetching */
  EXTERN(int) jpeg_huff_decode
-         (bitread_working_state * state, register bit_buf_type get_buffer,
-          register int bits_left, d_derived_tbl * htbl, int min_bits);
+         (bitread_working_state *state, register bit_buf_type get_buffer,
+          register int bits_left, d_derived_tbl *htbl, int min_bits);
new file mode 100644
--- /dev/null
+++ b/media/libjpeg/LICENSE.md
@@ -0,0 +1,88 @@
+libjpeg-turbo Licenses
+======================
+
+libjpeg-turbo is covered by three compatible BSD-style open source licenses:
+
+- The IJG (Independent JPEG Group) License, which is listed in
+  [README.ijg](README.ijg)
+
+  This license applies to the libjpeg API library and associated programs
+  (any code inherited from libjpeg, and any modifications to that code.)
+
+- The Modified (3-clause) BSD License, which is listed in
+  [turbojpeg.c](turbojpeg.c)
+
+  This license covers the TurboJPEG API library and associated programs.
+
+- The zlib License, which is listed in [simd/jsimdext.inc](simd/jsimdext.inc)
+
+  This license is a subset of the other two, and it covers the libjpeg-turbo
+  SIMD extensions.
+
+
+Complying with the libjpeg-turbo Licenses
+=========================================
+
+This section provides a roll-up of the libjpeg-turbo licensing terms, to the
+best of our understanding.
+
+1.  If you are distributing a modified version of the libjpeg-turbo source,
+    then:
+
+    1.  You cannot alter or remove any existing copyright or license notices
+        from the source.
+
+        **Origin**
+        - Clause 1 of the IJG License
+        - Clause 1 of the Modified BSD License
+        - Clauses 1 and 3 of the zlib License
+
+    2.  You must add your own copyright notice to the header of each source
+        file you modified, so others can tell that you modified that file (if
+        there is not an existing copyright header in that file, then you can
+        simply add a notice stating that you modified the file.)
+
+        **Origin**
+        - Clause 1 of the IJG License
+        - Clause 2 of the zlib License
+
+    3.  You must include the IJG README file, and you must not alter any of the
+        copyright or license text in that file.
+
+        **Origin**
+        - Clause 1 of the IJG License
+
+2.  If you are distributing only libjpeg-turbo binaries without the source, or
+    if you are distributing an application that statically links with
+    libjpeg-turbo, then:
+
+    1.  Your product documentation must include a message stating:
+
+        This software is based in part on the work of the Independent JPEG
+        Group.
+
+        **Origin**
+        - Clause 2 of the IJG license
+
+    2.  If your binary distribution includes or uses the TurboJPEG API, then
+        your product documentation must include the text of the Modified BSD
+        License.
+
+        **Origin**
+        - Clause 2 of the Modified BSD License
+
+3.  You cannot use the name of the IJG or The libjpeg-turbo Project or the
+    contributors thereof in advertising, publicity, etc.
+
+    **Origin**
+    - IJG License
+    - Clause 3 of the Modified BSD License
+
+4.  The IJG and The libjpeg-turbo Project do not warrant libjpeg-turbo to be
+    free of defects, nor do we accept any liability for undesirable
+    consequences resulting from your use of the software.
+
+    **Origin**
+    - IJG License
+    - Modified BSD License
+    - zlib License
--- a/media/libjpeg/MOZCHANGES
+++ b/media/libjpeg/MOZCHANGES
@@ -19,23 +19,23 @@ To upgrade to a new revision of libjpeg-
   to libjpeg-turbo 1.1.0, the only files I kept which didn't match
 
     *.c  *.h *.asm *.inc
 
   were README and README-turbo.
 
   You can easily look for all non *.c, *.h, *.asm, and *.inc files by running
 
-    $ hg status -nu | grep -v '\(c\|h\|asm\|inc\)$'
+    $ hg status -nu | grep -v '\(c\|h\|asm\|inc\|md\|ijg\)$'
 
   Once you're comfortable that you're only deleting files you want to delete
   (and you've hg add'ed the files you want to keep), you can nuke the remaining
   files with
 
-    $ hg status -nu | grep -v '\(c\|h\|asm\|inc\)$' | xargs rm
+    $ hg status -nu | grep -v '\(c\|h\|asm\|inc\|md\|ijg\)$' | xargs rm
 
   A helpful command for finding the *.c files which aren't *currently* part of
   the build is
 
     diff <(ls *.c | sort) <(grep -o '\w*\.c' Makefile.in | sort)
 
   Of course, libjpeg-turbo might have added some new source files, so you'll
   have to look though and figure out which of these files to keep.
@@ -43,16 +43,20 @@ To upgrade to a new revision of libjpeg-
 * Update jconfig.h and jconfigint.h as noted previously.
 
 * Update moz.build to build any new files.
 
 * Finally, tell hg that we've added or removed some files:
 
     $ hg addremove
 
+== June 23, 2016 (libjpeg-turbo v1.5.0 3ff13e651bbe6de9c6f15d05235d1d4f26f63ffc 2016-05-31) ==
+
+* Updated to v1.5.0 release.
+
 == October 5, 2015 (libjpeg-turbo v1.4.2 d8da49effe6460d55239c4c009c57f42d8e4a494 2015-09-21) ==
 
 * Updated to v1.4.2 release.
 
 == January 15, 2015 (libjpeg-turbo v1.4.0 r1481 2015-01-07) ==
 
 * Updated to v1.4.0 release.
 
rename from media/libjpeg/README
rename to media/libjpeg/README.ijg
--- a/media/libjpeg/README
+++ b/media/libjpeg/README.ijg
@@ -1,12 +1,12 @@
 libjpeg-turbo note:  This file has been modified by The libjpeg-turbo Project
 to include only information relevant to libjpeg-turbo, to wordsmith certain
 sections, and to remove impolitic language that existed in the libjpeg v8
-README.  It is included only for reference.  Please see README-turbo.txt for
+README.  It is included only for reference.  Please see README.md for
 information specific to libjpeg-turbo.
 
 
 The Independent JPEG Group's JPEG software
 ==========================================
 
 This distribution contains a release of the Independent JPEG Group's free JPEG
 software.  You are welcome to redistribute this software and to use it for any
@@ -123,17 +123,17 @@ 3. You may not pretend that you wrote th
 
 In legalese:
 
 The authors make NO WARRANTY or representation, either express or implied,
 with respect to this software, its quality, accuracy, merchantability, or
 fitness for a particular purpose.  This software is provided "AS IS", and you,
 its user, assume the entire risk as to its quality and accuracy.
 
-This software is copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
+This software is copyright (C) 1991-2016, Thomas G. Lane, Guido Vollbeding.
 All Rights Reserved except as specified below.
 
 Permission is hereby granted to use, copy, modify, and distribute this
 software (or portions thereof) for any purpose, without fee, subject to these
 conditions:
 (1) If any part of the source code for this software is distributed, then this
 README file must be included, with this copyright and no-warranty notice
 unaltered; and any additions, deletions, or changes to the original files
@@ -161,21 +161,21 @@ assumed by the product vendor.
 
 The Unix configuration script "configure" was produced with GNU Autoconf.
 It is copyright by the Free Software Foundation but is freely distributable.
 The same holds for its supporting scripts (config.guess, config.sub,
 ltmain.sh).  Another support script, install-sh, is copyright by X Consortium
 but is also freely distributable.
 
 The IJG distribution formerly included code to read and write GIF files.
-To avoid entanglement with the Unisys LZW patent, GIF reading support has
-been removed altogether, and the GIF writer has been simplified to produce
-"uncompressed GIFs".  This technique does not use the LZW algorithm; the
-resulting GIF files are larger than usual, but are readable by all standard
-GIF decoders.
+To avoid entanglement with the Unisys LZW patent (now expired), GIF reading
+support has been removed altogether, and the GIF writer has been simplified
+to produce "uncompressed GIFs".  This technique does not use the LZW
+algorithm; the resulting GIF files are larger than usual, but are readable
+by all standard GIF decoders.
 
 We are required to state that
     "The Graphics Interchange Format(c) is the Copyright property of
     CompuServe Incorporated.  GIF(sm) is a Service Mark property of
     CompuServe Incorporated."
 
 
 REFERENCES
@@ -184,18 +184,18 @@ REFERENCES
 We recommend reading one or more of these references before trying to
 understand the innards of the JPEG software.
 
 The best short technical introduction to the JPEG compression algorithm is
 	Wallace, Gregory K.  "The JPEG Still Picture Compression Standard",
 	Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
 (Adjacent articles in that issue discuss MPEG motion picture compression,
 applications of JPEG, and related topics.)  If you don't have the CACM issue
-handy, a PostScript file containing a revised version of Wallace's article is
-available at http://www.ijg.org/files/wallace.ps.gz.  The file (actually
+handy, a PDF file containing a revised version of Wallace's article is
+available at http://www.ijg.org/files/Wallace.JPEG.pdf.  The file (actually
 a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
 omits the sample images that appeared in CACM, but it includes corrections
 and some added material.  Note: the Wallace article is copyright ACM and IEEE,
 and it may not be used for commercial purposes.
 
 A somewhat less technical, more leisurely introduction to JPEG can be found in
 "The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
 M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1.  This book provides
@@ -241,19 +241,17 @@ Although IJG's own code does not support
 uses our library to implement TIFF/JPEG per the Note.
 
 
 ARCHIVE LOCATIONS
 =================
 
 The "official" archive site for this software is www.ijg.org.
 The most recent released version can always be found there in
-directory "files".  This particular version will be archived as
-http://www.ijg.org/files/jpegsrc.v8d.tar.gz, and in Windows-compatible
-"zip" archive format as http://www.ijg.org/files/jpegsr8d.zip.
+directory "files".
 
 The JPEG FAQ (Frequently Asked Questions) article is a source of some
 general information about JPEG.
 It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
 and other news.answers archive sites, including the official news.answers
 archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
 If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
 with body
rename from media/libjpeg/README-turbo.txt
rename to media/libjpeg/README.md
--- a/media/libjpeg/README-turbo.txt
+++ b/media/libjpeg/README.md
@@ -1,339 +1,341 @@
-*******************************************************************************
-**     Background
-*******************************************************************************
+Background
+==========
 
 libjpeg-turbo is a JPEG image codec that uses SIMD instructions (MMX, SSE2,
-NEON) to accelerate baseline JPEG compression and decompression on x86, x86-64,
-and ARM systems.  On such systems, libjpeg-turbo is generally 2-4x as fast as
-libjpeg, all else being equal.  On other types of systems, libjpeg-turbo can
-still outperform libjpeg by a significant amount, by virtue of its
-highly-optimized Huffman coding routines.  In many cases, the performance of
-libjpeg-turbo rivals that of proprietary high-speed JPEG codecs.
+NEON, AltiVec) to accelerate baseline JPEG compression and decompression on
+x86, x86-64, ARM, and PowerPC systems.  On such systems, libjpeg-turbo is
+generally 2-6x as fast as libjpeg, all else being equal.  On other types of
+systems, libjpeg-turbo can still outperform libjpeg by a significant amount, by
+virtue of its highly-optimized Huffman coding routines.  In many cases, the
+performance of libjpeg-turbo rivals that of proprietary high-speed JPEG codecs.
 
 libjpeg-turbo implements both the traditional libjpeg API as well as the less
 powerful but more straightforward TurboJPEG API.  libjpeg-turbo also features
 colorspace extensions that allow it to compress from/decompress to 32-bit and
 big-endian pixel buffers (RGBX, XBGR, etc.), as well as a full-featured Java
 interface.
 
 libjpeg-turbo was originally based on libjpeg/SIMD, an MMX-accelerated
 derivative of libjpeg v6b developed by Miyasaka Masaru.  The TigerVNC and
 VirtualGL projects made numerous enhancements to the codec in 2009, and in
 early 2010, libjpeg-turbo spun off into an independent project, with the goal
 of making high-speed JPEG compression/decompression technology available to a
 broader range of users and developers.
 
 
-*******************************************************************************
-**     License
-*******************************************************************************
+License
+=======
 
 libjpeg-turbo is covered by three compatible BSD-style open source licenses.
-Refer to LICENSE.txt for a roll-up of license terms.
+Refer to [LICENSE.md](LICENSE.md) for a roll-up of license terms.
 
 
-*******************************************************************************
-**     Using libjpeg-turbo
-*******************************************************************************
+Building libjpeg-turbo
+======================
+
+Refer to [BUILDING.md](BUILDING.md) for complete instructions.
+
+
+Using libjpeg-turbo
+===================
 
 libjpeg-turbo includes two APIs that can be used to compress and decompress
 JPEG images:
 
-  TurboJPEG API:  This API provides an easy-to-use interface for compressing
-  and decompressing JPEG images in memory.  It also provides some functionality
-  that would not be straightforward to achieve using the underlying libjpeg
-  API, such as generating planar YUV images and performing multiple
-  simultaneous lossless transforms on an image.  The Java interface for
-  libjpeg-turbo is written on top of the TurboJPEG API.
+- **TurboJPEG API**  
+  This API provides an easy-to-use interface for compressing and decompressing
+  JPEG images in memory.  It also provides some functionality that would not be
+  straightforward to achieve using the underlying libjpeg API, such as
+  generating planar YUV images and performing multiple simultaneous lossless
+  transforms on an image.  The Java interface for libjpeg-turbo is written on
+  top of the TurboJPEG API.
 
-  libjpeg API:  This is the de facto industry-standard API for compressing and
-  decompressing JPEG images.  It is more difficult to use than the TurboJPEG
-  API but also more powerful.  The libjpeg API implementation in libjpeg-turbo
-  is both API/ABI-compatible and mathematically compatible with libjpeg v6b.
-  It can also optionally be configured to be API/ABI-compatible with libjpeg v7
-  and v8 (see below.)
+- **libjpeg API**  
+  This is the de facto industry-standard API for compressing and decompressing
+  JPEG images.  It is more difficult to use than the TurboJPEG API but also
+  more powerful.  The libjpeg API implementation in libjpeg-turbo is both
+  API/ABI-compatible and mathematically compatible with libjpeg v6b.  It can
+  also optionally be configured to be API/ABI-compatible with libjpeg v7 and v8
+  (see below.)
 
 There is no significant performance advantage to either API when both are used
 to perform similar operations.
 
-=====================
 Colorspace Extensions
-=====================
+---------------------
 
 libjpeg-turbo includes extensions that allow JPEG images to be compressed
 directly from (and decompressed directly to) buffers that use BGR, BGRX,
 RGBX, XBGR, and XRGB pixel ordering.  This is implemented with ten new
 colorspace constants:
 
-  JCS_EXT_RGB   /* red/green/blue */
-  JCS_EXT_RGBX  /* red/green/blue/x */
-  JCS_EXT_BGR   /* blue/green/red */
-  JCS_EXT_BGRX  /* blue/green/red/x */
-  JCS_EXT_XBGR  /* x/blue/green/red */
-  JCS_EXT_XRGB  /* x/red/green/blue */
-  JCS_EXT_RGBA  /* red/green/blue/alpha */
-  JCS_EXT_BGRA  /* blue/green/red/alpha */
-  JCS_EXT_ABGR  /* alpha/blue/green/red */
-  JCS_EXT_ARGB  /* alpha/red/green/blue */
+    JCS_EXT_RGB   /* red/green/blue */
+    JCS_EXT_RGBX  /* red/green/blue/x */
+    JCS_EXT_BGR   /* blue/green/red */
+    JCS_EXT_BGRX  /* blue/green/red/x */
+    JCS_EXT_XBGR  /* x/blue/green/red */
+    JCS_EXT_XRGB  /* x/red/green/blue */
+    JCS_EXT_RGBA  /* red/green/blue/alpha */
+    JCS_EXT_BGRA  /* blue/green/red/alpha */
+    JCS_EXT_ABGR  /* alpha/blue/green/red */
+    JCS_EXT_ARGB  /* alpha/red/green/blue */
 
-Setting cinfo.in_color_space (compression) or cinfo.out_color_space
+Setting `cinfo.in_color_space` (compression) or `cinfo.out_color_space`
 (decompression) to one of these values will cause libjpeg-turbo to read the
 red, green, and blue values from (or write them to) the appropriate position in
 the pixel when compressing from/decompressing to an RGB buffer.
 
 Your application can check for the existence of these extensions at compile
 time with:
 
-  #ifdef JCS_EXTENSIONS
+    #ifdef JCS_EXTENSIONS
 
 At run time, attempting to use these extensions with a libjpeg implementation
 that does not support them will result in a "Bogus input colorspace" error.
 Applications can trap this error in order to test whether run-time support is
 available for the colorspace extensions.
 
 When using the RGBX, BGRX, XBGR, and XRGB colorspaces during decompression, the
 X byte is undefined, and in order to ensure the best performance, libjpeg-turbo
 can set that byte to whatever value it wishes.  If an application expects the X
-byte to be used as an alpha channel, then it should specify JCS_EXT_RGBA,
-JCS_EXT_BGRA, JCS_EXT_ABGR, or JCS_EXT_ARGB.  When these colorspace constants
-are used, the X byte is guaranteed to be 0xFF, which is interpreted as opaque.
+byte to be used as an alpha channel, then it should specify `JCS_EXT_RGBA`,
+`JCS_EXT_BGRA`, `JCS_EXT_ABGR`, or `JCS_EXT_ARGB`.  When these colorspace
+constants are used, the X byte is guaranteed to be 0xFF, which is interpreted
+as opaque.
 
 Your application can check for the existence of the alpha channel colorspace
 extensions at compile time with:
 
-  #ifdef JCS_ALPHA_EXTENSIONS
+    #ifdef JCS_ALPHA_EXTENSIONS
 
-jcstest.c, located in the libjpeg-turbo source tree, demonstrates how to check
-for the existence of the colorspace extensions at compile time and run time.
+[jcstest.c](jcstest.c), located in the libjpeg-turbo source tree, demonstrates
+how to check for the existence of the colorspace extensions at compile time and
+run time.
 
-===================================
 libjpeg v7 and v8 API/ABI Emulation
-===================================
+-----------------------------------
 
 With libjpeg v7 and v8, new features were added that necessitated extending the
 compression and decompression structures.  Unfortunately, due to the exposed
 nature of those structures, extending them also necessitated breaking backward
 ABI compatibility with previous libjpeg releases.  Thus, programs that were
 built to use libjpeg v7 or v8 did not work with libjpeg-turbo, since it is
 based on the libjpeg v6b code base.  Although libjpeg v7 and v8 are not
 as widely used as v6b, enough programs (including a few Linux distros) made
 the switch that there was a demand to emulate the libjpeg v7 and v8 ABIs
 in libjpeg-turbo.  It should be noted, however, that this feature was added
 primarily so that applications that had already been compiled to use libjpeg
 v7+ could take advantage of accelerated baseline JPEG encoding/decoding
 without recompiling.  libjpeg-turbo does not claim to support all of the
 libjpeg v7+ features, nor to produce identical output to libjpeg v7+ in all
 cases (see below.)
 
-By passing an argument of --with-jpeg7 or --with-jpeg8 to configure, or an
-argument of -DWITH_JPEG7=1 or -DWITH_JPEG8=1 to cmake, you can build a version
-of libjpeg-turbo that emulates the libjpeg v7 or v8 ABI, so that programs
-that are built against libjpeg v7 or v8 can be run with libjpeg-turbo.  The
-following section describes which libjpeg v7+ features are supported and which
-aren't.
+By passing an argument of `--with-jpeg7` or `--with-jpeg8` to `configure`, or
+an argument of `-DWITH_JPEG7=1` or `-DWITH_JPEG8=1` to `cmake`, you can build a
+version of libjpeg-turbo that emulates the libjpeg v7 or v8 ABI, so that
+programs that are built against libjpeg v7 or v8 can be run with libjpeg-turbo.
+The following section describes which libjpeg v7+ features are supported and
+which aren't.
+
+### Support for libjpeg v7 and v8 Features
 
-Support for libjpeg v7 and v8 Features:
----------------------------------------
-
-Fully supported:
+#### Fully supported
 
--- libjpeg: IDCT scaling extensions in decompressor
-   libjpeg-turbo supports IDCT scaling with scaling factors of 1/8, 1/4, 3/8,
-   1/2, 5/8, 3/4, 7/8, 9/8, 5/4, 11/8, 3/2, 13/8, 7/4, 15/8, and 2/1 (only 1/4
-   and 1/2 are SIMD-accelerated.)
+- **libjpeg: IDCT scaling extensions in decompressor**  
+  libjpeg-turbo supports IDCT scaling with scaling factors of 1/8, 1/4, 3/8,
+  1/2, 5/8, 3/4, 7/8, 9/8, 5/4, 11/8, 3/2, 13/8, 7/4, 15/8, and 2/1 (only 1/4
+  and 1/2 are SIMD-accelerated.)
 
--- libjpeg: arithmetic coding
+- **libjpeg: Arithmetic coding**
 
--- libjpeg: In-memory source and destination managers
-   See notes below.
+- **libjpeg: In-memory source and destination managers**  
+  See notes below.
 
--- cjpeg: Separate quality settings for luminance and chrominance
-   Note that the libpjeg v7+ API was extended to accommodate this feature only
-   for convenience purposes.  It has always been possible to implement this
-   feature with libjpeg v6b (see rdswitch.c for an example.)
+- **cjpeg: Separate quality settings for luminance and chrominance**  
+  Note that the libpjeg v7+ API was extended to accommodate this feature only
+  for convenience purposes.  It has always been possible to implement this
+  feature with libjpeg v6b (see rdswitch.c for an example.)
 
--- cjpeg: 32-bit BMP support
+- **cjpeg: 32-bit BMP support**
 
--- cjpeg: -rgb option
+- **cjpeg: `-rgb` option**
 
--- jpegtran: lossless cropping
+- **jpegtran: Lossless cropping**
 
--- jpegtran: -perfect option
+- **jpegtran: `-perfect` option**
 
--- jpegtran: forcing width/height when performing lossless crop
+- **jpegtran: Forcing width/height when performing lossless crop**
 
--- rdjpgcom: -raw option
+- **rdjpgcom: `-raw` option**
 
--- rdjpgcom: locale awareness
+- **rdjpgcom: Locale awareness**
 
 
-Not supported:
+#### Not supported
 
 NOTE:  As of this writing, extensive research has been conducted into the
 usefulness of DCT scaling as a means of data reduction and SmartScale as a
 means of quality improvement.  The reader is invited to peruse the research at
-http://www.libjpeg-turbo.org/About/SmartScale and draw his/her own conclusions,
+<http://www.libjpeg-turbo.org/About/SmartScale> and draw his/her own conclusions,
 but it is the general belief of our project that these features have not
 demonstrated sufficient usefulness to justify inclusion in libjpeg-turbo.
 
--- libjpeg: DCT scaling in compressor
-   cinfo.scale_num and cinfo.scale_denom are silently ignored.
-   There is no technical reason why DCT scaling could not be supported when
-   emulating the libjpeg v7+ API/ABI, but without the SmartScale extension (see
-   below), only scaling factors of 1/2, 8/15, 4/7, 8/13, 2/3, 8/11, 4/5, and
-   8/9 would be available, which is of limited usefulness.
+- **libjpeg: DCT scaling in compressor**  
+  `cinfo.scale_num` and `cinfo.scale_denom` are silently ignored.
+  There is no technical reason why DCT scaling could not be supported when
+  emulating the libjpeg v7+ API/ABI, but without the SmartScale extension (see
+  below), only scaling factors of 1/2, 8/15, 4/7, 8/13, 2/3, 8/11, 4/5, and
+  8/9 would be available, which is of limited usefulness.
 
--- libjpeg: SmartScale
-   cinfo.block_size is silently ignored.
-   SmartScale is an extension to the JPEG format that allows for DCT block
-   sizes other than 8x8.  Providing support for this new format would be
-   feasible (particularly without full acceleration.)  However, until/unless
-   the format becomes either an official industry standard or, at minimum, an
-   accepted solution in the community, we are hesitant to implement it, as
-   there is no sense of whether or how it might change in the future.  It is
-   our belief that SmartScale has not demonstrated sufficient usefulness as a
-   lossless format nor as a means of quality enhancement, and thus, our primary
-   interest in providing this feature would be as a means of supporting
-   additional DCT scaling factors.
+- **libjpeg: SmartScale**  
+  `cinfo.block_size` is silently ignored.
+  SmartScale is an extension to the JPEG format that allows for DCT block
+  sizes other than 8x8.  Providing support for this new format would be
+  feasible (particularly without full acceleration.)  However, until/unless
+  the format becomes either an official industry standard or, at minimum, an
+  accepted solution in the community, we are hesitant to implement it, as
+  there is no sense of whether or how it might change in the future.  It is
+  our belief that SmartScale has not demonstrated sufficient usefulness as a
+  lossless format nor as a means of quality enhancement, and thus our primary
+  interest in providing this feature would be as a means of supporting
+  additional DCT scaling factors.
 
--- libjpeg: Fancy downsampling in compressor
-   cinfo.do_fancy_downsampling is silently ignored.
-   This requires the DCT scaling feature, which is not supported.
+- **libjpeg: Fancy downsampling in compressor**  
+  `cinfo.do_fancy_downsampling` is silently ignored.
+  This requires the DCT scaling feature, which is not supported.
 
--- jpegtran: Scaling
-   This requires both the DCT scaling and SmartScale features, which are not
-   supported.
+- **jpegtran: Scaling**  
+  This requires both the DCT scaling and SmartScale features, which are not
+  supported.
 
--- Lossless RGB JPEG files
-   This requires the SmartScale feature, which is not supported.
+- **Lossless RGB JPEG files**  
+  This requires the SmartScale feature, which is not supported.
 
-What About libjpeg v9?
-----------------------
+### What About libjpeg v9?
 
 libjpeg v9 introduced yet another field to the JPEG compression structure
-(color_transform), thus making the ABI backward incompatible with that of
+(`color_transform`), thus making the ABI backward incompatible with that of
 libjpeg v8.  This new field was introduced solely for the purpose of supporting
-lossless SmartScale encoding.  Further, there was actually no reason to extend
-the API in this manner, as the color transform could have just as easily been
-activated by way of a new JPEG colorspace constant, thus preserving backward
-ABI compatibility.
+lossless SmartScale encoding.  Furthermore, there was actually no reason to
+extend the API in this manner, as the color transform could have just as easily
+been activated by way of a new JPEG colorspace constant, thus preserving
+backward ABI compatibility.
 
 Our research (see link above) has shown that lossless SmartScale does not
 generally accomplish anything that can't already be accomplished better with
-existing, standard lossless formats.  Thus, at this time, it is our belief that
-there is not sufficient technical justification for software to upgrade from
-libjpeg v8 to libjpeg v9, and therefore, not sufficient technical justification
-for us to emulate the libjpeg v9 ABI.
+existing, standard lossless formats.  Therefore, at this time it is our belief
+that there is not sufficient technical justification for software projects to
+upgrade from libjpeg v8 to libjpeg v9, and thus there is not sufficient
+echnical justification for us to emulate the libjpeg v9 ABI.
 
-=====================================
 In-Memory Source/Destination Managers
-=====================================
+-------------------------------------
 
-By default, libjpeg-turbo 1.3 and later includes the jpeg_mem_src() and
-jpeg_mem_dest() functions, even when not emulating the libjpeg v8 API/ABI.
+By default, libjpeg-turbo 1.3 and later includes the `jpeg_mem_src()` and
+`jpeg_mem_dest()` functions, even when not emulating the libjpeg v8 API/ABI.
 Previously, it was necessary to build libjpeg-turbo from source with libjpeg v8
 API/ABI emulation in order to use the in-memory source/destination managers,
 but several projects requested that those functions be included when emulating
 the libjpeg v6b API/ABI as well.  This allows the use of those functions by
-programs that need them without breaking ABI compatibility for programs that
+programs that need them, without breaking ABI compatibility for programs that
 don't, and it allows those functions to be provided in the "official"
 libjpeg-turbo binaries.
 
 Those who are concerned about maintaining strict conformance with the libjpeg
-v6b or v7 API can pass an argument of --without-mem-srcdst to configure or
-an argument of -DWITH_MEM_SRCDST=0 to CMake prior to building libjpeg-turbo.
-This will restore the pre-1.3 behavior, in which jpeg_mem_src() and
-jpeg_mem_dest() are only included when emulating the libjpeg v8 API/ABI.
+v6b or v7 API can pass an argument of `--without-mem-srcdst` to `configure` or
+an argument of `-DWITH_MEM_SRCDST=0` to `cmake` prior to building
+libjpeg-turbo.  This will restore the pre-1.3 behavior, in which
+`jpeg_mem_src()` and `jpeg_mem_dest()` are only included when emulating the
+libjpeg v8 API/ABI.
 
 On Un*x systems, including the in-memory source/destination managers changes
 the dynamic library version from 62.0.0 to 62.1.0 if using libjpeg v6b API/ABI
 emulation and from 7.0.0 to 7.1.0 if using libjpeg v7 API/ABI emulation.
 
 Note that, on most Un*x systems, the dynamic linker will not look for a
 function in a library until that function is actually used.  Thus, if a program
-is built against libjpeg-turbo 1.3+ and uses jpeg_mem_src() or jpeg_mem_dest(),
-that program will not fail if run against an older version of libjpeg-turbo or
-against libjpeg v7- until the program actually tries to call jpeg_mem_src() or
-jpeg_mem_dest().  Such is not the case on Windows.  If a program is built
-against the libjpeg-turbo 1.3+ DLL and uses jpeg_mem_src() or jpeg_mem_dest(),
-then it must use the libjpeg-turbo 1.3+ DLL at run time.
+is built against libjpeg-turbo 1.3+ and uses `jpeg_mem_src()` or
+`jpeg_mem_dest()`, that program will not fail if run against an older version
+of libjpeg-turbo or against libjpeg v7- until the program actually tries to
+call `jpeg_mem_src()` or `jpeg_mem_dest()`.  Such is not the case on Windows.
+If a program is built against the libjpeg-turbo 1.3+ DLL and uses
+`jpeg_mem_src()` or `jpeg_mem_dest()`, then it must use the libjpeg-turbo 1.3+
+DLL at run time.
 
 Both cjpeg and djpeg have been extended to allow testing the in-memory
 source/destination manager functions.  See their respective man pages for more
 details.
 
 
-*******************************************************************************
-**     Mathematical Compatibility
-*******************************************************************************
+Mathematical Compatibility
+==========================
 
 For the most part, libjpeg-turbo should produce identical output to libjpeg
 v6b.  The one exception to this is when using the floating point DCT/IDCT, in
 which case the outputs of libjpeg v6b and libjpeg-turbo can differ for the
 following reasons:
 
--- The SSE/SSE2 floating point DCT implementation in libjpeg-turbo is ever so
-   slightly more accurate than the implementation in libjpeg v6b, but not by
-   any amount perceptible to human vision (generally in the range of 0.01 to
-   0.08 dB gain in PNSR.)
--- When not using the SIMD extensions, libjpeg-turbo uses the more accurate
-   (and slightly faster) floating point IDCT algorithm introduced in libjpeg
-   v8a as opposed to the algorithm used in libjpeg v6b.  It should be noted,
-   however, that this algorithm basically brings the accuracy of the floating
-   point IDCT in line with the accuracy of the slow integer IDCT.  The floating
-   point DCT/IDCT algorithms are mainly a legacy feature, and they do not
-   produce significantly more accuracy than the slow integer algorithms (to put
-   numbers on this, the typical difference in PNSR between the two algorithms
-   is less than 0.10 dB, whereas changing the quality level by 1 in the upper
-   range of the quality scale is typically more like a 1.0 dB difference.)
--- If the floating point algorithms in libjpeg-turbo are not implemented using
-   SIMD instructions on a particular platform, then the accuracy of the
-   floating point DCT/IDCT can depend on the compiler settings.
+- The SSE/SSE2 floating point DCT implementation in libjpeg-turbo is ever so
+  slightly more accurate than the implementation in libjpeg v6b, but not by
+  any amount perceptible to human vision (generally in the range of 0.01 to
+  0.08 dB gain in PNSR.)
 
-While libjpeg-turbo does emulate the libjpeg v8 API/ABI, under the hood, it is
+- When not using the SIMD extensions, libjpeg-turbo uses the more accurate
+  (and slightly faster) floating point IDCT algorithm introduced in libjpeg
+  v8a as opposed to the algorithm used in libjpeg v6b.  It should be noted,
+  however, that this algorithm basically brings the accuracy of the floating
+  point IDCT in line with the accuracy of the slow integer IDCT.  The floating
+  point DCT/IDCT algorithms are mainly a legacy feature, and they do not
+  produce significantly more accuracy than the slow integer algorithms (to put
+  numbers on this, the typical difference in PNSR between the two algorithms
+  is less than 0.10 dB, whereas changing the quality level by 1 in the upper
+  range of the quality scale is typically more like a 1.0 dB difference.)
+
+- If the floating point algorithms in libjpeg-turbo are not implemented using
+  SIMD instructions on a particular platform, then the accuracy of the
+  floating point DCT/IDCT can depend on the compiler settings.
+
+While libjpeg-turbo does emulate the libjpeg v8 API/ABI, under the hood it is
 still using the same algorithms as libjpeg v6b, so there are several specific
 cases in which libjpeg-turbo cannot be expected to produce the same output as
 libjpeg v8:
 
--- When decompressing using scaling factors of 1/2 and 1/4, because libjpeg v8
-   implements those scaling algorithms differently than libjpeg v6b does, and
-   libjpeg-turbo's SIMD extensions are based on the libjpeg v6b behavior.
+- When decompressing using scaling factors of 1/2 and 1/4, because libjpeg v8
+  implements those scaling algorithms differently than libjpeg v6b does, and
+  libjpeg-turbo's SIMD extensions are based on the libjpeg v6b behavior.
 
--- When using chrominance subsampling, because libjpeg v8 implements this
-   with its DCT/IDCT scaling algorithms rather than with a separate
-   downsampling/upsampling algorithm.  In our testing, the subsampled/upsampled
-   output of libjpeg v8 is less accurate than that of libjpeg v6b for this
-   reason.
+- When using chrominance subsampling, because libjpeg v8 implements this
+  with its DCT/IDCT scaling algorithms rather than with a separate
+  downsampling/upsampling algorithm.  In our testing, the subsampled/upsampled
+  output of libjpeg v8 is less accurate than that of libjpeg v6b for this
+  reason.
 
--- When decompressing using a scaling factor > 1 and merged (AKA "non-fancy" or
-   "non-smooth") chrominance upsampling, because libjpeg v8 does not support
-   merged upsampling with scaling factors > 1.
+- When decompressing using a scaling factor > 1 and merged (AKA "non-fancy" or
+  "non-smooth") chrominance upsampling, because libjpeg v8 does not support
+  merged upsampling with scaling factors > 1.
 
 
-*******************************************************************************
-**     Performance Pitfalls
-*******************************************************************************
+Performance Pitfalls
+====================
 
-===============
 Restart Markers
-===============
+---------------
 
 The optimized Huffman decoder in libjpeg-turbo does not handle restart markers
 in a way that makes the rest of the libjpeg infrastructure happy, so it is
 necessary to use the slow Huffman decoder when decompressing a JPEG image that
 has restart markers.  This can cause the decompression performance to drop by
 as much as 20%, but the performance will still be much greater than that of
 libjpeg.  Many consumer packages, such as PhotoShop, use restart markers when
 generating JPEG images, so images generated by those programs will experience
 this issue.
 
-===============================================
 Fast Integer Forward DCT at High Quality Levels
-===============================================
+-----------------------------------------------
 
 The algorithm used by the SIMD-accelerated quantization function cannot produce
 correct results whenever the fast integer forward DCT is used along with a JPEG
 quality of 98-100.  Thus, libjpeg-turbo must use the non-SIMD quantization
 function in those cases.  This causes performance to drop by as much as 40%.
 It is therefore strongly advised that you use the slow integer forward DCT
 whenever encoding images with a JPEG quality of 98 or higher.
--- a/media/libjpeg/jaricom.c
+++ b/media/libjpeg/jaricom.c
@@ -1,39 +1,42 @@
 /*
  * jaricom.c
  *
+ * This file was part of the Independent JPEG Group's software:
  * Developed 1997-2009 by Guido Vollbeding.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
+ * libjpeg-turbo Modifications:
+ * Copyright (C) 2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains probability estimation tables for common use in
  * arithmetic entropy encoding and decoding routines.
  *
  * This data represents Table D.2 in the JPEG spec (ISO/IEC IS 10918-1
  * and CCITT Recommendation ITU-T T.81) and Table 24 in the JBIG spec
  * (ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82).
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
 
 /* The following #define specifies the packing of the four components
- * into the compact INT32 representation.
+ * into the compact JLONG representation.
  * Note that this formula must match the actual arithmetic encoder
  * and decoder implementation.  The implementation has to be changed
  * if this formula is changed.
  * The current organization is leaned on Markus Kuhn's JBIG
  * implementation (jbig_tab.c).
  */
 
-#define V(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b)
+#define V(i,a,b,c,d) (((JLONG)a << 16) | ((JLONG)c << 8) | ((JLONG)d << 7) | b)
 
-const INT32 jpeg_aritab[113+1] = {
+const JLONG jpeg_aritab[113+1] = {
 /*
  * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS
  */
   V(   0, 0x5a1d,   1,   1, 1 ),
   V(   1, 0x2586,  14,   2, 0 ),
   V(   2, 0x1114,  16,   3, 0 ),
   V(   3, 0x080b,  18,   4, 0 ),
   V(   4, 0x03d8,  20,   5, 0 ),
--- a/media/libjpeg/jcapimin.c
+++ b/media/libjpeg/jcapimin.c
@@ -1,17 +1,18 @@
 /*
  * jcapimin.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1998, Thomas G. Lane.
  * Modified 2003-2010 by Guido Vollbeding.
  * It was modified by The libjpeg-turbo Project to include only code relevant
  * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains application interface code for the compression half
  * of the JPEG library.  These are the "minimum" API routines that may be
  * needed in either the normal full-compression case or the transcoding-only
  * case.
  *
  * Most of the routines intended to be called directly by an application
  * are in this file or in jcapistd.c.  But also see jcparam.c for
@@ -44,18 +45,18 @@ jpeg_CreateCompress (j_compress_ptr cinf
 
   /* For debugging purposes, we zero the whole master structure.
    * But the application has already set the err pointer, and may have set
    * client_data, so we have to save and restore those fields.
    * Note: if application hasn't set client_data, tools like Purify may
    * complain here.
    */
   {
-    struct jpeg_error_mgr * err = cinfo->err;
-    void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+    struct jpeg_error_mgr *err = cinfo->err;
+    void *client_data = cinfo->client_data; /* ignore Purify complaint here */
     MEMZERO(cinfo, sizeof(struct jpeg_compress_struct));
     cinfo->err = err;
     cinfo->client_data = client_data;
   }
   cinfo->is_decompressor = FALSE;
 
   /* Initialize a memory manager instance for this object */
   jinit_memory_mgr((j_common_ptr) cinfo);
@@ -128,18 +129,18 @@ jpeg_abort_compress (j_compress_ptr cinf
  * since it is called by jpeg_start_compress, we put it here --- otherwise
  * jcparam.o would be linked whether the application used it or not.
  */
 
 GLOBAL(void)
 jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
 {
   int i;
-  JQUANT_TBL * qtbl;
-  JHUFF_TBL * htbl;
+  JQUANT_TBL *qtbl;
+  JHUFF_TBL *htbl;
 
   for (i = 0; i < NUM_QUANT_TBLS; i++) {
     if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
       qtbl->sent_table = suppress;
   }
 
   for (i = 0; i < NUM_HUFF_TBLS; i++) {
     if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
--- a/media/libjpeg/jcapistd.c
+++ b/media/libjpeg/jcapistd.c
@@ -1,14 +1,15 @@
 /*
  * jcapistd.c
  *
  * Copyright (C) 1994-1996, Thomas G. Lane.
  * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains application interface code for the compression half
  * of the JPEG library.  These are the "standard" API routines that are
  * used in the normal full-compression case.  They are not used by a
  * transcoding-only application.  Note that if an application links in
  * jpeg_start_compress, it will end up linking in the entire compressor.
  * We thus must separate this file from jcapimin.c to avoid linking the
  * whole compression library into a transcoder.
--- a/media/libjpeg/jcarith.c
+++ b/media/libjpeg/jcarith.c
@@ -1,16 +1,17 @@
 /*
  * jcarith.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Developed 1997-2009 by Guido Vollbeding.
- * It was modified by The libjpeg-turbo Project to include only code relevant
- * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * libjpeg-turbo Modifications:
+ * Copyright (C) 2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains portable arithmetic entropy encoding routines for JPEG
  * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81).
  *
  * Both sequential and progressive modes are supported in this single module.
  *
  * Suspension is not currently supported in this module.
  */
@@ -20,39 +21,39 @@
 #include "jpeglib.h"
 
 
 /* Expanded entropy encoder object for arithmetic encoding. */
 
 typedef struct {
   struct jpeg_entropy_encoder pub; /* public fields */
 
-  INT32 c; /* C register, base of coding interval, layout as in sec. D.1.3 */
-  INT32 a;               /* A register, normalized size of coding interval */
-  INT32 sc;        /* counter for stacked 0xFF values which might overflow */
-  INT32 zc;          /* counter for pending 0x00 output values which might *
+  JLONG c; /* C register, base of coding interval, layout as in sec. D.1.3 */
+  JLONG a;               /* A register, normalized size of coding interval */
+  JLONG sc;        /* counter for stacked 0xFF values which might overflow */
+  JLONG zc;          /* counter for pending 0x00 output values which might *
                           * be discarded at the end ("Pacman" termination) */
   int ct;  /* bit shift counter, determines when next byte will be written */
   int buffer;                /* buffer for most recent output byte != 0xFF */
 
   int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
   int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */
 
   unsigned int restarts_to_go;  /* MCUs left in this restart interval */
   int next_restart_num;         /* next restart number to write (0-7) */
 
   /* Pointers to statistics areas (these workspaces have image lifespan) */
-  unsigned char * dc_stats[NUM_ARITH_TBLS];
-  unsigned char * ac_stats[NUM_ARITH_TBLS];
+  unsigned char *dc_stats[NUM_ARITH_TBLS];
+  unsigned char *ac_stats[NUM_ARITH_TBLS];
 
   /* Statistics bin for coding with fixed probability 0.5 */
   unsigned char fixed_bin[4];
 } arith_entropy_encoder;
 
-typedef arith_entropy_encoder * arith_entropy_ptr;
+typedef arith_entropy_encoder *arith_entropy_ptr;
 
 /* The following two definitions specify the allocation chunk size
  * for the statistics area.
  * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least
  * 49 statistics bins for DC, and 245 statistics bins for AC coding.
  *
  * We use a compact representation with 1 byte per statistics bin,
  * thus the numbers directly represent byte sizes.
@@ -92,18 +93,18 @@ typedef arith_entropy_encoder * arith_en
  * statistical model is already rather stable.
  *
  * Thus, at the moment, we use the default conditioning values
  * anyway, and do not use the custom formula.
  *
 #define CALCULATE_SPECTRAL_CONDITIONING
  */
 
-/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
- * We assume that int right shift is unsigned if INT32 right shift is,
+/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than JLONG.
+ * We assume that int right shift is unsigned if JLONG right shift is,
  * which should be safe.
  */
 
 #ifdef RIGHT_SHIFT_IS_UNSIGNED
 #define ISHIFT_TEMPS    int ishift_temp;
 #define IRIGHT_SHIFT(x,shft)  \
         ((ishift_temp = (x)) < 0 ? \
          (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
@@ -113,34 +114,34 @@ typedef arith_entropy_encoder * arith_en
 #define IRIGHT_SHIFT(x,shft)    ((x) >> (shft))
 #endif
 
 
 LOCAL(void)
 emit_byte (int val, j_compress_ptr cinfo)
 /* Write next output byte; we do not support suspension in this module. */
 {
-  struct jpeg_destination_mgr * dest = cinfo->dest;
+  struct jpeg_destination_mgr *dest = cinfo->dest;
 
   *dest->next_output_byte++ = (JOCTET) val;
   if (--dest->free_in_buffer == 0)
     if (! (*dest->empty_output_buffer) (cinfo))
       ERREXIT(cinfo, JERR_CANT_SUSPEND);
 }
 
 
 /*
  * Finish up at the end of an arithmetic-compressed scan.
  */
 
 METHODDEF(void)
 finish_pass (j_compress_ptr cinfo)
 {
   arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
-  INT32 temp;
+  JLONG temp;
 
   /* Section D.1.8: Termination of encoding */
 
   /* Find the e->c in the coding interval with the largest
    * number of trailing zero bits */
   if ((temp = (e->a - 1 + e->c) & 0xFFFF0000L) < e->c)
     e->c = temp + 0x8000L;
   else
@@ -217,17 +218,17 @@ finish_pass (j_compress_ptr cinfo)
  * derived from Markus Kuhn's JBIG implementation.
  */
 
 LOCAL(void)
 arith_encode (j_compress_ptr cinfo, unsigned char *st, int val)
 {
   register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
   register unsigned char nl, nm;
-  register INT32 qe, temp;
+  register JLONG qe, temp;
   register int sv;
 
   /* Fetch values from our compact representation of Table D.2:
    * Qe values and probability estimation state machine
    */
   sv = *st;
   qe = jpeg_aritab[sv & 0x7F];  /* => Qe_Value */
   nl = qe & 0xFF; qe >>= 8;     /* Next_Index_LPS + Switch_MPS */
@@ -317,17 +318,17 @@ arith_encode (j_compress_ptr cinfo, unsi
  * Emit a restart marker & resynchronize predictions.
  */
 
 LOCAL(void)
 emit_restart (j_compress_ptr cinfo, int restart_num)
 {
   arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
   int ci;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   finish_pass(cinfo);
 
   emit_byte(0xFF, cinfo);
   emit_byte(JPEG_RST0 + restart_num, cinfo);
 
   /* Re-initialize statistics areas */
   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
@@ -677,17 +678,17 @@ encode_mcu_AC_refine (j_compress_ptr cin
 /*
  * Encode and output one MCU's worth of arithmetic-compressed coefficients.
  */
 
 METHODDEF(boolean)
 encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
 {
   arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
   JBLOCKROW block;
   unsigned char *st;
   int blkn, ci, tbl, k, ke;
   int v, v2, m;
 
   /* Emit restart marker if needed */
   if (cinfo->restart_interval) {
     if (entropy->restarts_to_go == 0) {
@@ -820,17 +821,17 @@ encode_mcu (j_compress_ptr cinfo, JBLOCK
  * Initialize for an arithmetic-compressed scan.
  */
 
 METHODDEF(void)
 start_pass (j_compress_ptr cinfo, boolean gather_statistics)
 {
   arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
   int ci, tbl;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   if (gather_statistics)
     /* Make sure to avoid that in the master control logic!
      * We are fully adaptive here and need no extra
      * statistics gathering pass!
      */
     ERREXIT(cinfo, JERR_NOT_COMPILED);
 
--- a/media/libjpeg/jccoefct.c
+++ b/media/libjpeg/jccoefct.c
@@ -1,16 +1,17 @@
 /*
  * jccoefct.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1997, Thomas G. Lane.
  * It was modified by The libjpeg-turbo Project to include only code and
  * information relevant to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains the coefficient buffer controller for compression.
  * This controller is the top level of the JPEG compressor proper.
  * The coefficient buffer lies between forward-DCT and entropy encoding steps.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
@@ -48,17 +49,17 @@ typedef struct {
    * current MCU's blocks within the virtual arrays.
    */
   JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
 
   /* In multi-pass modes, we need a virtual block array for each component. */
   jvirt_barray_ptr whole_image[MAX_COMPONENTS];
 } my_coef_controller;
 
-typedef my_coef_controller * my_coef_ptr;
+typedef my_coef_controller *my_coef_ptr;
 
 
 /* Forward declarations */
 METHODDEF(boolean) compress_data
         (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
 #ifdef FULL_COEF_BUFFER_SUPPORTED
 METHODDEF(boolean) compress_first_pass
         (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
--- a/media/libjpeg/jccolext.c
+++ b/media/libjpeg/jccolext.c
@@ -1,16 +1,17 @@
 /*
  * jccolext.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1996, Thomas G. Lane.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2009-2012, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2009-2012, 2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains input colorspace conversion routines.
  */
 
 
 /* This file is included by jccolor.c */
 
 
@@ -29,17 +30,17 @@
 INLINE
 LOCAL(void)
 rgb_ycc_convert_internal (j_compress_ptr cinfo,
                           JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
                           JDIMENSION output_row, int num_rows)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
   register int r, g, b;
-  register INT32 * ctab = cconvert->rgb_ycc_tab;
+  register JLONG * ctab = cconvert->rgb_ycc_tab;
   register JSAMPROW inptr;
   register JSAMPROW outptr0, outptr1, outptr2;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->image_width;
 
   while (--num_rows >= 0) {
     inptr = *input_buf++;
     outptr0 = output_buf[0][output_row];
@@ -86,17 +87,17 @@ rgb_ycc_convert_internal (j_compress_ptr
 INLINE
 LOCAL(void)
 rgb_gray_convert_internal (j_compress_ptr cinfo,
                            JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
                            JDIMENSION output_row, int num_rows)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
   register int r, g, b;
-  register INT32 * ctab = cconvert->rgb_ycc_tab;
+  register JLONG * ctab = cconvert->rgb_ycc_tab;
   register JSAMPROW inptr;
   register JSAMPROW outptr;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->image_width;
 
   while (--num_rows >= 0) {
     inptr = *input_buf++;
     outptr = output_buf[0][output_row];
--- a/media/libjpeg/jccolor.c
+++ b/media/libjpeg/jccolor.c
@@ -1,18 +1,19 @@
 /*
  * jccolor.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1996, Thomas G. Lane.
  * libjpeg-turbo Modifications:
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright (C) 2009-2012, 2015 D. R. Commander.
- * Copyright (C) 2014, MIPS Technologies, Inc., California
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2009-2012, 2015, D. R. Commander.
+ * Copyright (C) 2014, MIPS Technologies, Inc., California.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains input colorspace conversion routines.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
 #include "jsimd.h"
@@ -20,20 +21,20 @@
 
 
 /* Private subobject */
 
 typedef struct {
   struct jpeg_color_converter pub; /* public fields */
 
   /* Private state for RGB->YCC conversion */
-  INT32 * rgb_ycc_tab;          /* => table for RGB to YCbCr conversion */
+  JLONG *rgb_ycc_tab;           /* => table for RGB to YCbCr conversion */
 } my_color_converter;
 
-typedef my_color_converter * my_cconvert_ptr;
+typedef my_color_converter *my_cconvert_ptr;
 
 
 /**************** RGB -> YCbCr conversion: most common case **************/
 
 /*
  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
  * The conversion equations to be implemented are therefore
@@ -57,19 +58,19 @@ typedef my_color_converter * my_cconvert
  * for 12-bit samples it is still acceptable.  It's not very reasonable for
  * 16-bit samples, but if you want lossless storage you shouldn't be changing
  * colorspace anyway.
  * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
  * in the tables to save adding them separately in the inner loop.
  */
 
 #define SCALEBITS       16      /* speediest right-shift on some machines */
-#define CBCR_OFFSET     ((INT32) CENTERJSAMPLE << SCALEBITS)
-#define ONE_HALF        ((INT32) 1 << (SCALEBITS-1))
-#define FIX(x)          ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+#define CBCR_OFFSET     ((JLONG) CENTERJSAMPLE << SCALEBITS)
+#define ONE_HALF        ((JLONG) 1 << (SCALEBITS-1))
+#define FIX(x)          ((JLONG) ((x) * (1L<<SCALEBITS) + 0.5))
 
 /* We allocate one big table and divide it up into eight parts, instead of
  * doing eight alloc_small requests.  This lets us use a single table base
  * address, which can be held in a register in the inner loops on many
  * machines (more than can hold all eight addresses, anyway).
  */
 
 #define R_Y_OFF         0                       /* offset to R => Y section */
@@ -192,23 +193,23 @@ typedef my_color_converter * my_cconvert
 /*
  * Initialize for RGB->YCC colorspace conversion.
  */
 
 METHODDEF(void)
 rgb_ycc_start (j_compress_ptr cinfo)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
-  INT32 * rgb_ycc_tab;
-  INT32 i;
+  JLONG *rgb_ycc_tab;
+  JLONG i;
 
   /* Allocate and fill in the conversion tables. */
-  cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
+  cconvert->rgb_ycc_tab = rgb_ycc_tab = (JLONG *)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
-                                (TABLE_SIZE * sizeof(INT32)));
+                                (TABLE_SIZE * sizeof(JLONG)));
 
   for (i = 0; i <= MAXJSAMPLE; i++) {
     rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
     rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
     rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i     + ONE_HALF;
     rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
     rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
     /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
@@ -376,17 +377,17 @@ rgb_rgb_convert (j_compress_ptr cinfo,
 
 METHODDEF(void)
 cmyk_ycck_convert (j_compress_ptr cinfo,
                    JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
                    JDIMENSION output_row, int num_rows)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
   register int r, g, b;
-  register INT32 * ctab = cconvert->rgb_ycc_tab;
+  register JLONG *ctab = cconvert->rgb_ycc_tab;
   register JSAMPROW inptr;
   register JSAMPROW outptr0, outptr1, outptr2, outptr3;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->image_width;
 
   while (--num_rows >= 0) {
     inptr = *input_buf++;
     outptr0 = output_buf[0][output_row];
--- a/media/libjpeg/jcdctmgr.c
+++ b/media/libjpeg/jcdctmgr.c
@@ -1,80 +1,81 @@
 /*
  * jcdctmgr.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1996, Thomas G. Lane.
  * libjpeg-turbo Modifications:
  * Copyright (C) 1999-2006, MIYASAKA Masaru.
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright (C) 2011, 2014-2015 D. R. Commander
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2011, 2014-2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains the forward-DCT management logic.
  * This code selects a particular DCT implementation to be used,
  * and it performs related housekeeping chores including coefficient
  * quantization.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
 #include "jdct.h"               /* Private declarations for DCT subsystem */
 #include "jsimddct.h"
 
 
 /* Private subobject for this module */
 
-typedef void (*forward_DCT_method_ptr) (DCTELEM * data);
-typedef void (*float_DCT_method_ptr) (FAST_FLOAT * data);
+typedef void (*forward_DCT_method_ptr) (DCTELEM *data);
+typedef void (*float_DCT_method_ptr) (FAST_FLOAT *data);
 
 typedef void (*convsamp_method_ptr) (JSAMPARRAY sample_data,
                                      JDIMENSION start_col,
-                                     DCTELEM * workspace);
+                                     DCTELEM *workspace);
 typedef void (*float_convsamp_method_ptr) (JSAMPARRAY sample_data,
                                            JDIMENSION start_col,
                                            FAST_FLOAT *workspace);
 
-typedef void (*quantize_method_ptr) (JCOEFPTR coef_block, DCTELEM * divisors,
-                                     DCTELEM * workspace);
+typedef void (*quantize_method_ptr) (JCOEFPTR coef_block, DCTELEM *divisors,
+                                     DCTELEM *workspace);
 typedef void (*float_quantize_method_ptr) (JCOEFPTR coef_block,
-                                           FAST_FLOAT * divisors,
-                                           FAST_FLOAT * workspace);
+                                           FAST_FLOAT *divisors,
+                                           FAST_FLOAT *workspace);
 
 METHODDEF(void) quantize (JCOEFPTR, DCTELEM *, DCTELEM *);
 
 typedef struct {
   struct jpeg_forward_dct pub;  /* public fields */
 
   /* Pointer to the DCT routine actually in use */
   forward_DCT_method_ptr dct;
   convsamp_method_ptr convsamp;
   quantize_method_ptr quantize;
 
   /* The actual post-DCT divisors --- not identical to the quant table
    * entries, because of scaling (especially for an unnormalized DCT).
    * Each table is given in normal array order.
    */
-  DCTELEM * divisors[NUM_QUANT_TBLS];
+  DCTELEM *divisors[NUM_QUANT_TBLS];
 
   /* work area for FDCT subroutine */
-  DCTELEM * workspace;
+  DCTELEM *workspace;
 
 #ifdef DCT_FLOAT_SUPPORTED
   /* Same as above for the floating-point case. */
   float_DCT_method_ptr float_dct;
   float_convsamp_method_ptr float_convsamp;
   float_quantize_method_ptr float_quantize;
-  FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
-  FAST_FLOAT * float_workspace;
+  FAST_FLOAT *float_divisors[NUM_QUANT_TBLS];
+  FAST_FLOAT *float_workspace;
 #endif
 } my_fdct_controller;
 
-typedef my_fdct_controller * my_fdct_ptr;
+typedef my_fdct_controller *my_fdct_ptr;
 
 
 #if BITS_IN_JSAMPLE == 8
 
 /*
  * Find the highest bit in an integer through binary search.
  */
 
@@ -164,32 +165,32 @@ flss (UINT16 val)
  * half" operation.
  *
  * Lastly, we store each of the values in their own table instead
  * of in a consecutive manner, yet again in order to allow SIMD
  * routines.
  */
 
 LOCAL(int)
-compute_reciprocal (UINT16 divisor, DCTELEM * dtbl)
+compute_reciprocal (UINT16 divisor, DCTELEM *dtbl)
 {
   UDCTELEM2 fq, fr;
   UDCTELEM c;
   int b, r;
 
   if (divisor == 1) {
     /* divisor == 1 means unquantized, so these reciprocal/correction/shift
      * values will cause the C quantization algorithm to act like the
      * identity function.  Since only the C quantization algorithm is used in
      * these cases, the scale value is irrelevant.
      */
     dtbl[DCTSIZE2 * 0] = (DCTELEM) 1;                       /* reciprocal */
     dtbl[DCTSIZE2 * 1] = (DCTELEM) 0;                       /* correction */
     dtbl[DCTSIZE2 * 2] = (DCTELEM) 1;                       /* scale */
-    dtbl[DCTSIZE2 * 3] = (DCTELEM) (-sizeof(DCTELEM) * 8);  /* shift */
+    dtbl[DCTSIZE2 * 3] = -(DCTELEM) (sizeof(DCTELEM) * 8);  /* shift */
     return 0;
   }
 
   b = flss(divisor) - 1;
   r  = sizeof(DCTELEM) * 8 + b;
 
   fq = ((UDCTELEM2)1 << r) / divisor;
   fr = ((UDCTELEM2)1 << r) % divisor;
@@ -203,17 +204,21 @@ compute_reciprocal (UINT16 divisor, DCTE
   } else if (fr <= (divisor / 2U)) { /* fractional part is < 0.5 */
     c++;
   } else { /* fractional part is > 0.5 */
     fq++;
   }
 
   dtbl[DCTSIZE2 * 0] = (DCTELEM) fq;      /* reciprocal */
   dtbl[DCTSIZE2 * 1] = (DCTELEM) c;       /* correction + roundfactor */
+#ifdef WITH_SIMD
   dtbl[DCTSIZE2 * 2] = (DCTELEM) (1 << (sizeof(DCTELEM)*8*2 - r));  /* scale */
+#else
+  dtbl[DCTSIZE2 * 2] = 1;
+#endif
   dtbl[DCTSIZE2 * 3] = (DCTELEM) r - sizeof(DCTELEM)*8; /* shift */
 
   if(r <= 16) return 0;
   else return 1;
 }
 
 #endif
 
@@ -228,18 +233,18 @@ compute_reciprocal (UINT16 divisor, DCTE
  */
 
 METHODDEF(void)
 start_pass_fdctmgr (j_compress_ptr cinfo)
 {
   my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
   int ci, qtblno, i;
   jpeg_component_info *compptr;
-  JQUANT_TBL * qtbl;
-  DCTELEM * dtbl;
+  JQUANT_TBL *qtbl;
+  DCTELEM *dtbl;
 
   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
        ci++, compptr++) {
     qtblno = compptr->quant_tbl_no;
     /* Make sure specified quantization table is present */
     if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
         cinfo->quant_tbl_ptrs[qtblno] == NULL)
       ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
@@ -255,18 +260,18 @@ start_pass_fdctmgr (j_compress_ptr cinfo
       if (fdct->divisors[qtblno] == NULL) {
         fdct->divisors[qtblno] = (DCTELEM *)
           (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
                                       (DCTSIZE2 * 4) * sizeof(DCTELEM));
       }
       dtbl = fdct->divisors[qtblno];
       for (i = 0; i < DCTSIZE2; i++) {
 #if BITS_IN_JSAMPLE == 8
-        if(!compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i])
-          && fdct->quantize == jsimd_quantize)
+        if (!compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]) &&
+            fdct->quantize == jsimd_quantize)
           fdct->quantize = quantize;
 #else
         dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
 #endif
       }
       break;
 #endif
 #ifdef DCT_IFAST_SUPPORTED
@@ -295,26 +300,26 @@ start_pass_fdctmgr (j_compress_ptr cinfo
         if (fdct->divisors[qtblno] == NULL) {
           fdct->divisors[qtblno] = (DCTELEM *)
             (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
                                         (DCTSIZE2 * 4) * sizeof(DCTELEM));
         }
         dtbl = fdct->divisors[qtblno];
         for (i = 0; i < DCTSIZE2; i++) {
 #if BITS_IN_JSAMPLE == 8
-          if(!compute_reciprocal(
-            DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
-                                  (INT32) aanscales[i]),
-                    CONST_BITS-3), &dtbl[i])
-            && fdct->quantize == jsimd_quantize)
+          if (!compute_reciprocal(
+                DESCALE(MULTIPLY16V16((JLONG) qtbl->quantval[i],
+                                      (JLONG) aanscales[i]),
+                        CONST_BITS-3), &dtbl[i]) &&
+              fdct->quantize == jsimd_quantize)
             fdct->quantize = quantize;
 #else
            dtbl[i] = (DCTELEM)
-             DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
-                                   (INT32) aanscales[i]),
+             DESCALE(MULTIPLY16V16((JLONG) qtbl->quantval[i],
+                                   (JLONG) aanscales[i]),
                      CONST_BITS-3);
 #endif
         }
       }
       break;
 #endif
 #ifdef DCT_FLOAT_SUPPORTED
     case JDCT_FLOAT:
@@ -322,17 +327,17 @@ start_pass_fdctmgr (j_compress_ptr cinfo
         /* For float AA&N IDCT method, divisors are equal to quantization
          * coefficients scaled by scalefactor[row]*scalefactor[col], where
          *   scalefactor[0] = 1
          *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7
          * We apply a further scale factor of 8.
          * What's actually stored is 1/divisor so that the inner loop can
          * use a multiplication rather than a division.
          */
-        FAST_FLOAT * fdtbl;
+        FAST_FLOAT *fdtbl;
         int row, col;
         static const double aanscalefactor[DCTSIZE] = {
           1.0, 1.387039845, 1.306562965, 1.175875602,
           1.0, 0.785694958, 0.541196100, 0.275899379
         };
 
         if (fdct->float_divisors[qtblno] == NULL) {
           fdct->float_divisors[qtblno] = (FAST_FLOAT *)
@@ -360,17 +365,17 @@ start_pass_fdctmgr (j_compress_ptr cinfo
 }
 
 
 /*
  * Load data into workspace, applying unsigned->signed conversion.
  */
 
 METHODDEF(void)
-convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM * workspace)
+convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace)
 {
   register DCTELEM *workspaceptr;
   register JSAMPROW elemptr;
   register int elemr;
 
   workspaceptr = workspace;
   for (elemr = 0; elemr < DCTSIZE; elemr++) {
     elemptr = sample_data[elemr] + start_col;
@@ -395,17 +400,17 @@ convsamp (JSAMPARRAY sample_data, JDIMEN
 }
 
 
 /*
  * Quantize/descale the coefficients, and store into coef_blocks[].
  */
 
 METHODDEF(void)
-quantize (JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace)
+quantize (JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
 {
   int i;
   DCTELEM temp;
   JCOEFPTR output_ptr = coef_block;
 
 #if BITS_IN_JSAMPLE == 8
 
   UDCTELEM recip, corr;
@@ -417,22 +422,22 @@ quantize (JCOEFPTR coef_block, DCTELEM *
     recip = divisors[i + DCTSIZE2 * 0];
     corr =  divisors[i + DCTSIZE2 * 1];
     shift = divisors[i + DCTSIZE2 * 3];
 
     if (temp < 0) {
       temp = -temp;
       product = (UDCTELEM2)(temp + corr) * recip;
       product >>= shift + sizeof(DCTELEM)*8;
-      temp = product;
+      temp = (DCTELEM)product;
       temp = -temp;
     } else {
       product = (UDCTELEM2)(temp + corr) * recip;
       product >>= shift + sizeof(DCTELEM)*8;
-      temp = product;
+      temp = (DCTELEM)product;
     }
     output_ptr[i] = (JCOEF) temp;
   }
 
 #else
 
   register DCTELEM qval;
 
@@ -477,26 +482,26 @@ quantize (JCOEFPTR coef_block, DCTELEM *
  * Perform forward DCT on one or more blocks of a component.
  *
  * The input samples are taken from the sample_data[] array starting at
  * position start_row/start_col, and moving to the right for any additional
  * blocks. The quantized coefficients are returned in coef_blocks[].
  */
 
 METHODDEF(void)
-forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
+forward_DCT (j_compress_ptr cinfo, jpeg_component_info *compptr,
              JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
              JDIMENSION start_row, JDIMENSION start_col,
              JDIMENSION num_blocks)
 /* This version is used for integer DCT implementations. */
 {
   /* This routine is heavily used, so it's worth coding it tightly. */
   my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
-  DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
-  DCTELEM * workspace;
+  DCTELEM *divisors = fdct->divisors[compptr->quant_tbl_no];
+  DCTELEM *workspace;
   JDIMENSION bi;
 
   /* Make sure the compiler doesn't look up these every pass */
   forward_DCT_method_ptr do_dct = fdct->dct;
   convsamp_method_ptr do_convsamp = fdct->convsamp;
   quantize_method_ptr do_quantize = fdct->quantize;
   workspace = fdct->workspace;
 
@@ -514,17 +519,17 @@ forward_DCT (j_compress_ptr cinfo, jpeg_
   }
 }
 
 
 #ifdef DCT_FLOAT_SUPPORTED
 
 
 METHODDEF(void)
-convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT * workspace)
+convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace)
 {
   register FAST_FLOAT *workspaceptr;
   register JSAMPROW elemptr;
   register int elemr;
 
   workspaceptr = workspace;
   for (elemr = 0; elemr < DCTSIZE; elemr++) {
     elemptr = sample_data[elemr] + start_col;
@@ -545,17 +550,17 @@ convsamp_float (JSAMPARRAY sample_data, 
                           (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
     }
 #endif
   }
 }
 
 
 METHODDEF(void)
-quantize_float (JCOEFPTR coef_block, FAST_FLOAT * divisors, FAST_FLOAT * workspace)
+quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors, FAST_FLOAT *workspace)
 {
   register FAST_FLOAT temp;
   register int i;
   register JCOEFPTR output_ptr = coef_block;
 
   for (i = 0; i < DCTSIZE2; i++) {
     /* Apply the quantization and scaling factor */
     temp = workspace[i] * divisors[i];
@@ -567,26 +572,26 @@ quantize_float (JCOEFPTR coef_block, FAS
      * code should work for either 16-bit or 32-bit ints.
      */
     output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
   }
 }
 
 
 METHODDEF(void)
-forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
+forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info *compptr,
                    JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
                    JDIMENSION start_row, JDIMENSION start_col,
                    JDIMENSION num_blocks)
 /* This version is used for floating-point DCT implementations. */
 {
   /* This routine is heavily used, so it's worth coding it tightly. */
   my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
-  FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
-  FAST_FLOAT * workspace;
+  FAST_FLOAT *divisors = fdct->float_divisors[compptr->quant_tbl_no];
+  FAST_FLOAT *workspace;
   JDIMENSION bi;
 
 
   /* Make sure the compiler doesn't look up these every pass */
   float_DCT_method_ptr do_dct = fdct->float_dct;
   float_convsamp_method_ptr do_convsamp = fdct->float_convsamp;
   float_quantize_method_ptr do_quantize = fdct->float_quantize;
   workspace = fdct->float_workspace;
--- a/media/libjpeg/jchuff.c
+++ b/media/libjpeg/jchuff.c
@@ -1,30 +1,33 @@
 /*
  * jchuff.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, 2014-2015 D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2009-2011, 2014-2016, D. R. Commander.
+ * Copyright (C) 2015, Matthieu Darbois.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains Huffman entropy encoding routines.
  *
  * Much of the complexity here has to do with supporting output suspension.
  * If the data destination module demands suspension, we want to be able to
  * back up to the start of the current MCU.  To do this, we copy state
  * variables into local working storage, and update them back to the
  * permanent JPEG objects only upon successful completion of an MCU.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
-#include "jchuff.h"             /* Declarations shared with jcphuff.c */
+#include "jsimd.h"
+#include "jconfigint.h"
 #include <limits.h>
 
 /*
  * NOTE: If USE_CLZ_INTRINSIC is defined, then clz/bsr instructions will be
  * used for bit counting rather than the lookup table.  This will reduce the
  * memory footprint by 64k, which is important for some mobile applications
  * that create many isolated instances of libjpeg-turbo (web browsers, for
  * instance.)  This may improve performance on some mobile platforms as well.
@@ -94,33 +97,35 @@ typedef struct {
 
   savable_state saved;          /* Bit buffer & DC state at start of MCU */
 
   /* These fields are NOT loaded into local working state. */
   unsigned int restarts_to_go;  /* MCUs left in this restart interval */
   int next_restart_num;         /* next restart number to write (0-7) */
 
   /* Pointers to derived tables (these workspaces have image lifespan) */
-  c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
-  c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+  c_derived_tbl *dc_derived_tbls[NUM_HUFF_TBLS];
+  c_derived_tbl *ac_derived_tbls[NUM_HUFF_TBLS];
 
 #ifdef ENTROPY_OPT_SUPPORTED    /* Statistics tables for optimization */
-  long * dc_count_ptrs[NUM_HUFF_TBLS];
-  long * ac_count_ptrs[NUM_HUFF_TBLS];
+  long *dc_count_ptrs[NUM_HUFF_TBLS];
+  long *ac_count_ptrs[NUM_HUFF_TBLS];
 #endif
+
+  int simd;
 } huff_entropy_encoder;
 
-typedef huff_entropy_encoder * huff_entropy_ptr;
+typedef huff_entropy_encoder *huff_entropy_ptr;
 
 /* Working state while writing an MCU.
  * This struct contains all the fields that are needed by subroutines.
  */
 
 typedef struct {
-  JOCTET * next_output_byte;    /* => next byte to write in buffer */
+  JOCTET *next_output_byte;     /* => next byte to write in buffer */
   size_t free_in_buffer;        /* # of byte spaces remaining in buffer */
   savable_state cur;            /* Current bit buffer & DC state */
   j_compress_ptr cinfo;         /* dump_buffer needs access to this */
 } working_state;
 
 
 /* Forward declarations */
 METHODDEF(boolean) encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data);
@@ -138,30 +143,32 @@ METHODDEF(void) finish_pass_gather (j_co
  * just count the Huffman symbols used and generate Huffman code tables.
  */
 
 METHODDEF(void)
 start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
 {
   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
   int ci, dctbl, actbl;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   if (gather_statistics) {
 #ifdef ENTROPY_OPT_SUPPORTED
     entropy->pub.encode_mcu = encode_mcu_gather;
     entropy->pub.finish_pass = finish_pass_gather;
 #else
     ERREXIT(cinfo, JERR_NOT_COMPILED);
 #endif
   } else {
     entropy->pub.encode_mcu = encode_mcu_huff;
     entropy->pub.finish_pass = finish_pass_huff;
   }
 
+  entropy->simd = jsimd_can_huff_encode_one_block();
+
   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
     compptr = cinfo->cur_comp_info[ci];
     dctbl = compptr->dc_tbl_no;
     actbl = compptr->ac_tbl_no;
     if (gather_statistics) {
 #ifdef ENTROPY_OPT_SUPPORTED
       /* Check for invalid table indexes */
       /* (make_c_derived_tbl does this in the other path) */
@@ -208,17 +215,17 @@ start_pass_huff (j_compress_ptr cinfo, b
  * Compute the derived values for a Huffman table.
  * This routine also performs some validation checks on the table.
  *
  * Note this is also used by jcphuff.c.
  */
 
 GLOBAL(void)
 jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
-                         c_derived_tbl ** pdtbl)
+                         c_derived_tbl **pdtbl)
 {
   JHUFF_TBL *htbl;
   c_derived_tbl *dtbl;
   int p, i, l, lastp, si, maxsymbol;
   char huffsize[257];
   unsigned int huffcode[257];
   unsigned int code;
 
@@ -263,17 +270,17 @@ jpeg_make_c_derived_tbl (j_compress_ptr 
   while (huffsize[p]) {
     while (((int) huffsize[p]) == si) {
       huffcode[p++] = code;
       code++;
     }
     /* code is now 1 more than the last code used for codelength si; but
      * it must still fit in si bits, since no code is allowed to be all ones.
      */
-    if (((INT32) code) >= (((INT32) 1) << si))
+    if (((JLONG) code) >= (((JLONG) 1) << si))
       ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
     code <<= 1;
     si++;
   }
 
   /* Figure C.3: generate encoding tables */
   /* These are code and size indexed by symbol value */
 
@@ -306,20 +313,20 @@ jpeg_make_c_derived_tbl (j_compress_ptr 
 #define emit_byte(state,val,action)  \
         { *(state)->next_output_byte++ = (JOCTET) (val);  \
           if (--(state)->free_in_buffer == 0)  \
             if (! dump_buffer(state))  \
               { action; } }
 
 
 LOCAL(boolean)
-dump_buffer (working_state * state)
+dump_buffer (working_state *state)
 /* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
 {
-  struct jpeg_destination_mgr * dest = state->cinfo->dest;
+  struct jpeg_destination_mgr *dest = state->cinfo->dest;
 
   if (! (*dest->empty_output_buffer) (state->cinfo))
     return FALSE;
   /* After a successful buffer dump, must reset buffer pointers */
   state->next_output_byte = dest->next_output_byte;
   state->free_in_buffer = dest->free_in_buffer;
   return TRUE;
 }
@@ -383,31 +390,31 @@ dump_buffer (working_state * state)
 #if SIZEOF_SIZE_T==8 || defined(_WIN64)
 
 #define EMIT_BITS(code, size) { \
   CHECKBUF47() \
   PUT_BITS(code, size) \
 }
 
 #define EMIT_CODE(code, size) { \
-  temp2 &= (((INT32) 1)<<nbits) - 1; \
+  temp2 &= (((JLONG) 1)<<nbits) - 1; \
   CHECKBUF31() \
   PUT_BITS(code, size) \
   PUT_BITS(temp2, nbits) \
  }
 
 #else
 
 #define EMIT_BITS(code, size) { \
   PUT_BITS(code, size) \
   CHECKBUF15() \
 }
 
 #define EMIT_CODE(code, size) { \
-  temp2 &= (((INT32) 1)<<nbits) - 1; \
+  temp2 &= (((JLONG) 1)<<nbits) - 1; \
   PUT_BITS(code, size) \
   CHECKBUF15() \
   PUT_BITS(temp2, nbits) \
   CHECKBUF15() \
  }
 
 #endif
 
@@ -449,17 +456,17 @@ dump_buffer (working_state * state)
   else { \
     state->free_in_buffer -= (buffer - state->next_output_byte); \
     state->next_output_byte = buffer; \
   } \
  }
 
 
 LOCAL(boolean)
-flush_bits (working_state * state)
+flush_bits (working_state *state)
 {
   JOCTET _buffer[BUFSIZE], *buffer;
   size_t put_buffer;  int put_bits;
   size_t bytes, bytestocopy;  int localbuf = 0;
 
   put_buffer = state->cur.put_buffer;
   put_bits = state->cur.put_bits;
   LOAD_BUFFER()
@@ -474,17 +481,34 @@ flush_bits (working_state * state)
 
   return TRUE;
 }
 
 
 /* Encode a single block's worth of coefficients */
 
 LOCAL(boolean)
-encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
+encode_one_block_simd (working_state *state, JCOEFPTR block, int last_dc_val,
+                       c_derived_tbl *dctbl, c_derived_tbl *actbl)
+{
+  JOCTET _buffer[BUFSIZE], *buffer;
+  size_t bytes, bytestocopy;  int localbuf = 0;
+
+  LOAD_BUFFER()
+
+  buffer = jsimd_huff_encode_one_block(state, buffer, block, last_dc_val,
+                                       dctbl, actbl);
+
+  STORE_BUFFER()
+
+  return TRUE;
+}
+
+LOCAL(boolean)
+encode_one_block (working_state *state, JCOEFPTR block, int last_dc_val,
                   c_derived_tbl *dctbl, c_derived_tbl *actbl)
 {
   int temp, temp2, temp3;
   int nbits;
   int r, code, size;
   JOCTET _buffer[BUFSIZE], *buffer;
   size_t put_buffer;  int put_bits;
   int code_0xf0 = actbl->ehufco[0xf0], size_0xf0 = actbl->ehufsi[0xf0];
@@ -515,17 +539,17 @@ encode_one_block (working_state * state,
   nbits = JPEG_NBITS(temp);
 
   /* Emit the Huffman-coded symbol for the number of bits */
   code = dctbl->ehufco[nbits];
   size = dctbl->ehufsi[nbits];
   EMIT_BITS(code, size)
 
   /* Mask off any extra bits in code */
-  temp2 &= (((INT32) 1)<<nbits) - 1;
+  temp2 &= (((JLONG) 1)<<nbits) - 1;
 
   /* Emit that number of bits of the value, if positive, */
   /* or the complement of its magnitude, if negative. */
   EMIT_BITS(temp2, nbits)
 
   /* Encode the AC coefficients per section F.1.2.2 */
 
   r = 0;                        /* r = run length of zeros */
@@ -587,17 +611,17 @@ encode_one_block (working_state * state,
 }
 
 
 /*
  * Emit a restart marker & resynchronize predictions.
  */
 
 LOCAL(boolean)
-emit_restart (working_state * state, int restart_num)
+emit_restart (working_state *state, int restart_num)
 {
   int ci;
 
   if (! flush_bits(state))
     return FALSE;
 
   emit_byte(state, 0xFF, return FALSE);
   emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
@@ -617,42 +641,56 @@ emit_restart (working_state * state, int
  */
 
 METHODDEF(boolean)
 encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
 {
   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
   working_state state;
   int blkn, ci;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   /* Load up working state */
   state.next_output_byte = cinfo->dest->next_output_byte;
   state.free_in_buffer = cinfo->dest->free_in_buffer;
   ASSIGN_STATE(state.cur, entropy->saved);
   state.cinfo = cinfo;
 
   /* Emit restart marker if needed */
   if (cinfo->restart_interval) {
     if (entropy->restarts_to_go == 0)
       if (! emit_restart(&state, entropy->next_restart_num))
         return FALSE;
   }
 
   /* Encode the MCU data blocks */
-  for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
-    ci = cinfo->MCU_membership[blkn];
-    compptr = cinfo->cur_comp_info[ci];
-    if (! encode_one_block(&state,
-                           MCU_data[blkn][0], state.cur.last_dc_val[ci],
-                           entropy->dc_derived_tbls[compptr->dc_tbl_no],
-                           entropy->ac_derived_tbls[compptr->ac_tbl_no]))
-      return FALSE;
-    /* Update last_dc_val */
-    state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
+  if (entropy->simd) {
+    for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+      ci = cinfo->MCU_membership[blkn];
+      compptr = cinfo->cur_comp_info[ci];
+      if (! encode_one_block_simd(&state,
+                                  MCU_data[blkn][0], state.cur.last_dc_val[ci],
+                                  entropy->dc_derived_tbls[compptr->dc_tbl_no],
+                                  entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+        return FALSE;
+      /* Update last_dc_val */
+      state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
+    }
+  } else {
+    for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+      ci = cinfo->MCU_membership[blkn];
+      compptr = cinfo->cur_comp_info[ci];
+      if (! encode_one_block(&state,
+                             MCU_data[blkn][0], state.cur.last_dc_val[ci],
+                             entropy->dc_derived_tbls[compptr->dc_tbl_no],
+                             entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+        return FALSE;
+      /* Update last_dc_val */
+      state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
+    }
   }
 
   /* Completed MCU, so update state */
   cinfo->dest->next_output_byte = state.next_output_byte;
   cinfo->dest->free_in_buffer = state.free_in_buffer;
   ASSIGN_STATE(entropy->saved, state.cur);
 
   /* Update restart-interval state too */
@@ -785,17 +823,17 @@ htest_one_block (j_compress_ptr cinfo, J
  * No data is actually output, so no suspension return is possible.
  */
 
 METHODDEF(boolean)
 encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
 {
   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
   int blkn, ci;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   /* Take care of restart intervals if needed */
   if (cinfo->restart_interval) {
     if (entropy->restarts_to_go == 0) {
       /* Re-initialize DC predictions to 0 */
       for (ci = 0; ci < cinfo->comps_in_scan; ci++)
         entropy->saved.last_dc_val[ci] = 0;
       /* Update restart state */
@@ -841,17 +879,17 @@ encode_mcu_gather (j_compress_ptr cinfo,
  * typically only very-low-frequency symbols will be given less-than-optimal
  * lengths, so the code is almost optimal.  Experimental comparisons against
  * an optimal limited-length-code algorithm indicate that the difference is
  * microscopic --- usually less than a hundredth of a percent of total size.
  * So the extra complexity of an optimal algorithm doesn't seem worthwhile.
  */
 
 GLOBAL(void)
-jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])
+jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
 {
 #define MAX_CLEN 32             /* assumed maximum initial code length */
   UINT8 bits[MAX_CLEN+1];       /* bits[k] = # of symbols with code length k */
   int codesize[257];            /* codesize[k] = code length of symbol k */
   int others[257];              /* next symbol in current branch of tree */
   int c1, c2;
   int p, i, j;
   long v;
@@ -986,17 +1024,17 @@ jpeg_gen_optimal_table (j_compress_ptr c
  * Finish up a statistics-gathering pass and create the new Huffman tables.
  */
 
 METHODDEF(void)
 finish_pass_gather (j_compress_ptr cinfo)
 {
   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
   int ci, dctbl, actbl;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
   JHUFF_TBL **htblptr;
   boolean did_dc[NUM_HUFF_TBLS];
   boolean did_ac[NUM_HUFF_TBLS];
 
   /* It's important not to apply jpeg_gen_optimal_table more than once
    * per table, because it clobbers the input frequency counts!
    */
   MEMZERO(did_dc, sizeof(did_dc));
--- a/media/libjpeg/jchuff.h
+++ b/media/libjpeg/jchuff.h
@@ -1,16 +1,17 @@
 /*
  * jchuff.h
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * It was modified by The libjpeg-turbo Project to include only code relevant
  * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains declarations for Huffman entropy encoding routines
  * that are shared between the sequential encoder (jchuff.c) and the
  * progressive encoder (jcphuff.c).  No other modules need to see these.
  */
 
 /* The legal range of a DCT coefficient is
  *  -1024 .. +1023  for 8-bit data;
@@ -34,9 +35,9 @@ typedef struct {
 
 /* Expand a Huffman table definition into the derived format */
 EXTERN(void) jpeg_make_c_derived_tbl
         (j_compress_ptr cinfo, boolean isDC, int tblno,
          c_derived_tbl ** pdtbl);
 
 /* Generate an optimal table definition given the specified counts */
 EXTERN(void) jpeg_gen_optimal_table
-        (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]);
+        (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]);
--- a/media/libjpeg/jcinit.c
+++ b/media/libjpeg/jcinit.c
@@ -1,14 +1,15 @@
 /*
  * jcinit.c
  *
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains initialization logic for the JPEG compressor.
  * This routine is in charge of selecting the modules to be executed and
  * making an initialization call to each one.
  *
  * Logically, this code belongs in jcmaster.c.  It's split out because
  * linking this routine implies linking the entire compression library.
  * For a transcoding-only application, we want to be able to use jcmaster.c
--- a/media/libjpeg/jcmainct.c
+++ b/media/libjpeg/jcmainct.c
@@ -1,16 +1,17 @@
 /*
  * jcmainct.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1996, Thomas G. Lane.
  * It was modified by The libjpeg-turbo Project to include only code relevant
  * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains the main buffer controller for compression.
  * The main buffer lies between the pre-processor and the JPEG
  * compressor proper; it holds downsampled data in the JPEG colorspace.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
@@ -29,17 +30,17 @@ typedef struct {
 
   /* If using just a strip buffer, this points to the entire set of buffers
    * (we allocate one for each component).  In the full-image case, this
    * points to the currently accessible strips of the virtual arrays.
    */
   JSAMPARRAY buffer[MAX_COMPONENTS];
 } my_main_controller;
 
-typedef my_main_controller * my_main_ptr;
+typedef my_main_controller *my_main_ptr;
 
 
 /* Forward declarations */
 METHODDEF(void) process_data_simple_main
         (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
          JDIMENSION in_rows_avail);
 
 
--- a/media/libjpeg/jcmarker.c
+++ b/media/libjpeg/jcmarker.c
@@ -1,17 +1,18 @@
 /*
  * jcmarker.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1998, Thomas G. Lane.
  * Modified 2003-2010 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
  * Copyright (C) 2010, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains routines to write JPEG datastream markers.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
 #include "jpegcomp.h"
@@ -88,17 +89,17 @@ typedef enum {                  /* JPEG 
 /* Private state */
 
 typedef struct {
   struct jpeg_marker_writer pub; /* public fields */
 
   unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */
 } my_marker_writer;
 
-typedef my_marker_writer * my_marker_ptr;
+typedef my_marker_writer *my_marker_ptr;
 
 
 /*
  * Basic output routines.
  *
  * Note that we do not support suspension while writing a marker.
  * Therefore, an application using suspension must ensure that there is
  * enough buffer space for the initial markers (typ. 600-700 bytes) before
@@ -107,17 +108,17 @@ typedef my_marker_writer * my_marker_ptr
  * modes are not supported at all with suspension, so those two are the only
  * points where markers will be written.
  */
 
 LOCAL(void)
 emit_byte (j_compress_ptr cinfo, int val)
 /* Emit a byte */
 {
-  struct jpeg_destination_mgr * dest = cinfo->dest;
+  struct jpeg_destination_mgr *dest = cinfo->dest;
 
   *(dest->next_output_byte)++ = (JOCTET) val;
   if (--dest->free_in_buffer == 0) {
     if (! (*dest->empty_output_buffer) (cinfo))
       ERREXIT(cinfo, JERR_CANT_SUSPEND);
   }
 }
 
@@ -144,17 +145,17 @@ emit_2bytes (j_compress_ptr cinfo, int v
  * Routines to write specific marker types.
  */
 
 LOCAL(int)
 emit_dqt (j_compress_ptr cinfo, int index)
 /* Emit a DQT marker */
 /* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
 {
-  JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
+  JQUANT_TBL *qtbl = cinfo->quant_tbl_ptrs[index];
   int prec;
   int i;
 
   if (qtbl == NULL)
     ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
 
   prec = 0;
   for (i = 0; i < DCTSIZE2; i++) {
@@ -183,17 +184,17 @@ emit_dqt (j_compress_ptr cinfo, int inde
   return prec;
 }
 
 
 LOCAL(void)
 emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
 /* Emit a DHT marker */
 {
-  JHUFF_TBL * htbl;
+  JHUFF_TBL *htbl;
   int length, i;
 
   if (is_ac) {
     htbl = cinfo->ac_huff_tbl_ptrs[index];
     index += 0x10;              /* output index has AC bit set */
   } else {
     htbl = cinfo->dc_huff_tbl_ptrs[index];
   }
--- a/media/libjpeg/jcmaster.c
+++ b/media/libjpeg/jcmaster.c
@@ -1,28 +1,30 @@
 /*
  * jcmaster.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * Modified 2003-2010 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2010, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2010, 2016, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains master control logic for the JPEG compressor.
  * These routines are concerned with parameter validation, initial setup,
  * and inter-pass control (determining the number of passes and the work
  * to be done in each pass).
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
 #include "jpegcomp.h"
+#include "jconfigint.h"
 
 
 /* Private state */
 
 typedef enum {
         main_pass,              /* input data, also do first output step */
         huff_opt_pass,          /* Huffman code optimization pass */
         output_pass             /* data output pass */
@@ -32,19 +34,29 @@ typedef struct {
   struct jpeg_comp_master pub;  /* public fields */
 
   c_pass_type pass_type;        /* the type of the current pass */
 
   int pass_number;              /* # of passes completed */
   int total_passes;             /* total # of passes needed */
 
   int scan_number;              /* current index in scan_info[] */
+
+  /*
+   * This is here so we can add libjpeg-turbo version/build information to the
+   * global string table without introducing a new global symbol.  Adding this
+   * information to the global string table allows one to examine a binary
+   * object and determine which version of libjpeg-turbo it was built from or
+   * linked against.
+   */
+  const char *jpeg_version;
+
 } my_comp_master;
 
-typedef my_comp_master * my_master_ptr;
+typedef my_comp_master *my_master_ptr;
 
 
 /*
  * Support routines that do various essential calculations.
  */
 
 #if JPEG_LIB_VERSION >= 70
 /*
@@ -162,22 +174,22 @@ initial_setup (j_compress_ptr cinfo, boo
 #ifdef C_MULTISCAN_FILES_SUPPORTED
 
 LOCAL(void)
 validate_script (j_compress_ptr cinfo)
 /* Verify that the scan script in cinfo->scan_info[] is valid; also
  * determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
  */
 {
-  const jpeg_scan_info * scanptr;
+  const jpeg_scan_info *scanptr;
   int scanno, ncomps, ci, coefi, thisi;
   int Ss, Se, Ah, Al;
   boolean component_sent[MAX_COMPONENTS];
 #ifdef C_PROGRESSIVE_SUPPORTED
-  int * last_bitpos_ptr;
+  int *last_bitpos_ptr;
   int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
   /* -1 until that coefficient has been seen; then last Al for it */
 #endif
 
   if (cinfo->num_scans <= 0)
     ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
 
   /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
@@ -303,17 +315,17 @@ select_scan_parameters (j_compress_ptr c
 /* Set up the scan parameters for the current scan */
 {
   int ci;
 
 #ifdef C_MULTISCAN_FILES_SUPPORTED
   if (cinfo->scan_info != NULL) {
     /* Prepare for current scan --- the script is already validated */
     my_master_ptr master = (my_master_ptr) cinfo->master;
-    const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number;
+    const jpeg_scan_info *scanptr = cinfo->scan_info + master->scan_number;
 
     cinfo->comps_in_scan = scanptr->comps_in_scan;
     for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
       cinfo->cur_comp_info[ci] =
         &cinfo->comp_info[scanptr->component_index[ci]];
     }
     cinfo->Ss = scanptr->Ss;
     cinfo->Se = scanptr->Se;
@@ -597,17 +609,17 @@ jinit_c_master_control (j_compress_ptr c
 #else
     ERREXIT(cinfo, JERR_NOT_COMPILED);
 #endif
   } else {
     cinfo->progressive_mode = FALSE;
     cinfo->num_scans = 1;
   }
 
-  if (cinfo->progressive_mode && !cinfo->arith_code)    /*  TEMPORARY HACK ??? */
+  if (cinfo->progressive_mode && !cinfo->arith_code)  /*  TEMPORARY HACK ??? */
     cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */
 
   /* Initialize my private state */
   if (transcode_only) {
     /* no main pass in transcoding */
     if (cinfo->optimize_coding)
       master->pass_type = huff_opt_pass;
     else
@@ -617,9 +629,11 @@ jinit_c_master_control (j_compress_ptr c
     master->pass_type = main_pass;
   }
   master->scan_number = 0;
   master->pass_number = 0;
   if (cinfo->optimize_coding)
     master->total_passes = cinfo->num_scans * 2;
   else
     master->total_passes = cinfo->num_scans;
+
+  master->jpeg_version = PACKAGE_NAME " version " VERSION " (build " BUILD ")";
 }
--- a/media/libjpeg/jcomapi.c
+++ b/media/libjpeg/jcomapi.c
@@ -1,16 +1,17 @@
 /*
  * jcomapi.c
  *
  * This file was part of the Independent JPEG Group's software:
- * Copyright (C) 1994-1997, Thomas G. Lane.0
+ * Copyright (C) 1994-1997, Thomas G. Lane.
  * It was modified by The libjpeg-turbo Project to include only code relevant
  * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains application interface routines that are used for both
  * compression and decompression.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
--- a/media/libjpeg/jcparam.c
+++ b/media/libjpeg/jcparam.c
@@ -1,17 +1,18 @@
 /*
  * jcparam.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1998, Thomas G. Lane.
  * Modified 2003-2008 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
  * Copyright (C) 2009-2011, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains optional default-setting code for the JPEG compressor.
  * Applications do not have to use this file, but those that don't use it
  * must know a lot more about the innards of the JPEG code.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
@@ -28,17 +29,17 @@ jpeg_add_quant_table (j_compress_ptr cin
                       const unsigned int *basic_table,
                       int scale_factor, boolean force_baseline)
 /* Define a quantization table equal to the basic_table times
  * a scale factor (given as a percentage).
  * If force_baseline is TRUE, the computed quantization table entries
  * are limited to 1..255 for JPEG baseline compatibility.
  */
 {
-  JQUANT_TBL ** qtblptr;
+  JQUANT_TBL **qtblptr;
   int i;
   long temp;
 
   /* Safety check to ensure start_compress not called yet. */
   if (cinfo->global_state != CSTATE_START)
     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
 
   if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
@@ -316,17 +317,17 @@ jpeg_default_colorspace (j_compress_ptr 
 
 /*
  * Set the JPEG colorspace, and choose colorspace-dependent default values.
  */
 
 GLOBAL(void)
 jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
 {
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
   int ci;
 
 #define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl)  \
   (compptr = &cinfo->comp_info[index], \
    compptr->component_id = (id), \
    compptr->h_samp_factor = (hsamp), \
    compptr->v_samp_factor = (vsamp), \
    compptr->quant_tbl_no = (quant), \
@@ -398,32 +399,32 @@ jpeg_set_colorspace (j_compress_ptr cinf
     ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
   }
 }
 
 
 #ifdef C_PROGRESSIVE_SUPPORTED
 
 LOCAL(jpeg_scan_info *)
-fill_a_scan (jpeg_scan_info * scanptr, int ci,
+fill_a_scan (jpeg_scan_info *scanptr, int ci,
              int Ss, int Se, int Ah, int Al)
 /* Support routine: generate one scan for specified component */
 {
   scanptr->comps_in_scan = 1;
   scanptr->component_index[0] = ci;
   scanptr->Ss = Ss;
   scanptr->Se = Se;
   scanptr->Ah = Ah;
   scanptr->Al = Al;
   scanptr++;
   return scanptr;
 }
 
 LOCAL(jpeg_scan_info *)
-fill_scans (jpeg_scan_info * scanptr, int ncomps,
+fill_scans (jpeg_scan_info *scanptr, int ncomps,
             int Ss, int Se, int Ah, int Al)
 /* Support routine: generate one scan for each component */
 {
   int ci;
 
   for (ci = 0; ci < ncomps; ci++) {
     scanptr->comps_in_scan = 1;
     scanptr->component_index[0] = ci;
@@ -432,17 +433,17 @@ fill_scans (jpeg_scan_info * scanptr, in
     scanptr->Ah = Ah;
     scanptr->Al = Al;
     scanptr++;
   }
   return scanptr;
 }
 
 LOCAL(jpeg_scan_info *)
-fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al)
+fill_dc_scans (jpeg_scan_info *scanptr, int ncomps, int Ah, int Al)
 /* Support routine: generate interleaved DC scan if possible, else N scans */
 {
   int ci;
 
   if (ncomps <= MAX_COMPS_IN_SCAN) {
     /* Single interleaved DC scan */
     scanptr->comps_in_scan = ncomps;
     for (ci = 0; ci < ncomps; ci++)
@@ -464,17 +465,17 @@ fill_dc_scans (jpeg_scan_info * scanptr,
  * cinfo->num_components and cinfo->jpeg_color_space must be correct.
  */
 
 GLOBAL(void)
 jpeg_simple_progression (j_compress_ptr cinfo)
 {
   int ncomps = cinfo->num_components;
   int nscans;
-  jpeg_scan_info * scanptr;
+  jpeg_scan_info *scanptr;
 
   /* Safety check to ensure start_compress not called yet. */
   if (cinfo->global_state != CSTATE_START)
     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
 
   /* Figure space needed for script.  Calculation must match code below! */
   if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
     /* Custom script for YCbCr color images. */
--- a/media/libjpeg/jcphuff.c
+++ b/media/libjpeg/jcphuff.c
@@ -1,16 +1,17 @@
 /*
  * jcphuff.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1995-1997, Thomas G. Lane.
- * It was modified by The libjpeg-turbo Project to include only code relevant
- * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * libjpeg-turbo Modifications:
+ * Copyright (C) 2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains Huffman entropy encoding routines for progressive JPEG.
  *
  * We do not support output suspension in this module, since the library
  * currently does not allow multiple-scan files to be written with output
  * suspension.
  */
 
@@ -27,57 +28,57 @@ typedef struct {
   struct jpeg_entropy_encoder pub; /* public fields */
 
   /* Mode flag: TRUE for optimization, FALSE for actual data output */
   boolean gather_statistics;
 
   /* Bit-level coding status.
    * next_output_byte/free_in_buffer are local copies of cinfo->dest fields.
    */
-  JOCTET * next_output_byte;    /* => next byte to write in buffer */
+  JOCTET *next_output_byte;     /* => next byte to write in buffer */
   size_t free_in_buffer;        /* # of byte spaces remaining in buffer */
-  INT32 put_buffer;             /* current bit-accumulation buffer */
+  size_t put_buffer;            /* current bit-accumulation buffer */
   int put_bits;                 /* # of bits now in it */
   j_compress_ptr cinfo;         /* link to cinfo (needed for dump_buffer) */
 
   /* Coding status for DC components */
   int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
 
   /* Coding status for AC components */
   int ac_tbl_no;                /* the table number of the single component */
   unsigned int EOBRUN;          /* run length of EOBs */
   unsigned int BE;              /* # of buffered correction bits before MCU */
-  char * bit_buffer;            /* buffer for correction bits (1 per char) */
+  char *bit_buffer;             /* buffer for correction bits (1 per char) */
   /* packing correction bits tightly would save some space but cost time... */
 
   unsigned int restarts_to_go;  /* MCUs left in this restart interval */
   int next_restart_num;         /* next restart number to write (0-7) */
 
   /* Pointers to derived tables (these workspaces have image lifespan).
    * Since any one scan codes only DC or only AC, we only need one set
    * of tables, not one for DC and one for AC.
    */
-  c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+  c_derived_tbl *derived_tbls[NUM_HUFF_TBLS];
 
   /* Statistics tables for optimization; again, one set is enough */
-  long * count_ptrs[NUM_HUFF_TBLS];
+  long *count_ptrs[NUM_HUFF_TBLS];
 } phuff_entropy_encoder;
 
-typedef phuff_entropy_encoder * phuff_entropy_ptr;
+typedef phuff_entropy_encoder *phuff_entropy_ptr;
 
 /* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
  * buffer can hold.  Larger sizes may slightly improve compression, but
  * 1000 is already well into the realm of overkill.
  * The minimum safe size is 64 bits.
  */
 
 #define MAX_CORR_BITS  1000     /* Max # of correction bits I can buffer */
 
-/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
- * We assume that int right shift is unsigned if INT32 right shift is,
+/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than JLONG.
+ * We assume that int right shift is unsigned if JLONG right shift is,
  * which should be safe.
  */
 
 #ifdef RIGHT_SHIFT_IS_UNSIGNED
 #define ISHIFT_TEMPS    int ishift_temp;
 #define IRIGHT_SHIFT(x,shft)  \
         ((ishift_temp = (x)) < 0 ? \
          (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
@@ -105,17 +106,17 @@ METHODDEF(void) finish_pass_gather_phuff
  */
 
 METHODDEF(void)
 start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
 {
   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
   boolean is_DC_band;
   int ci, tbl;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   entropy->cinfo = cinfo;
   entropy->gather_statistics = gather_statistics;
 
   is_DC_band = (cinfo->Ss == 0);
 
   /* We assume jcmaster.c already validated the scan parameters. */
 
@@ -202,17 +203,17 @@ start_pass_phuff (j_compress_ptr cinfo, 
           if (--(entropy)->free_in_buffer == 0)  \
             dump_buffer(entropy); }
 
 
 LOCAL(void)
 dump_buffer (phuff_entropy_ptr entropy)
 /* Empty the output buffer; we do not support suspension in this module. */
 {
-  struct jpeg_destination_mgr * dest = entropy->cinfo->dest;
+  struct jpeg_destination_mgr *dest = entropy->cinfo->dest;
 
   if (! (*dest->empty_output_buffer) (entropy->cinfo))
     ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
   /* After a successful buffer dump, must reset buffer pointers */
   entropy->next_output_byte = dest->next_output_byte;
   entropy->free_in_buffer = dest->free_in_buffer;
 }
 
@@ -225,27 +226,27 @@ dump_buffer (phuff_entropy_ptr entropy)
  * between calls, so 24 bits are sufficient.
  */
 
 LOCAL(void)
 emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
 /* Emit some bits, unless we are in gather mode */
 {
   /* This routine is heavily used, so it's worth coding tightly. */
-  register INT32 put_buffer = (INT32) code;
+  register size_t put_buffer = (size_t) code;
   register int put_bits = entropy->put_bits;
 
   /* if size is 0, caller used an invalid Huffman table entry */
   if (size == 0)
     ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
 
   if (entropy->gather_statistics)
     return;                     /* do nothing if we're only getting stats */
 
-  put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+  put_buffer &= (((size_t) 1)<<size) - 1; /* mask off any extra bits in code */
 
   put_bits += size;             /* new number of bits in buffer */
 
   put_buffer <<= 24 - put_bits; /* align incoming bits */
 
   put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
 
   while (put_bits >= 8) {
@@ -278,28 +279,28 @@ flush_bits (phuff_entropy_ptr entropy)
  */
 
 LOCAL(void)
 emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
 {
   if (entropy->gather_statistics)
     entropy->count_ptrs[tbl_no][symbol]++;
   else {
-    c_derived_tbl * tbl = entropy->derived_tbls[tbl_no];
+    c_derived_tbl *tbl = entropy->derived_tbls[tbl_no];
     emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]);
   }
 }
 
 
 /*
  * Emit bits from a correction bit buffer.
  */
 
 LOCAL(void)
-emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart,
+emit_buffered_bits (phuff_entropy_ptr entropy, char *bufstart,
                     unsigned int nbits)
 {
   if (entropy->gather_statistics)
     return;                     /* no real work */
 
   while (nbits > 0) {
     emit_bits(entropy, (unsigned int) (*bufstart), 1);
     bufstart++;
@@ -377,17 +378,17 @@ METHODDEF(boolean)
 encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
 {
   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
   register int temp, temp2;
   register int nbits;
   int blkn, ci;
   int Al = cinfo->Al;
   JBLOCKROW block;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
   ISHIFT_TEMPS
 
   entropy->next_output_byte = cinfo->dest->next_output_byte;
   entropy->free_in_buffer = cinfo->dest->free_in_buffer;
 
   /* Emit restart marker if needed */
   if (cinfo->restart_interval)
     if (entropy->restarts_to_go == 0)
@@ -764,17 +765,17 @@ finish_pass_phuff (j_compress_ptr cinfo)
  */
 
 METHODDEF(void)
 finish_pass_gather_phuff (j_compress_ptr cinfo)
 {
   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
   boolean is_DC_band;
   int ci, tbl;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
   JHUFF_TBL **htblptr;
   boolean did[NUM_HUFF_TBLS];
 
   /* Flush out buffered data (all we care about is counting the EOB symbol) */
   emit_eobrun(entropy);
 
   is_DC_band = (cinfo->Ss == 0);
 
--- a/media/libjpeg/jcprepct.c
+++ b/media/libjpeg/jcprepct.c
@@ -1,16 +1,17 @@
 /*
  * jcprepct.c
  *
  * This file is part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1996, Thomas G. Lane.
  * It was modified by The libjpeg-turbo Project to include only code relevant
  * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains the compression preprocessing controller.
  * This controller manages the color conversion, downsampling,
  * and edge expansion steps.
  *
  * Most of the complexity here is associated with buffering input rows
  * as required by the downsampler.  See the comments at the head of
  * jcsample.c for the downsampler's needs.
@@ -64,17 +65,17 @@ typedef struct {
   int next_buf_row;             /* index of next row to store in color_buf */
 
 #ifdef CONTEXT_ROWS_SUPPORTED   /* only needed for context case */
   int this_row_group;           /* starting row index of group to process */
   int next_buf_stop;            /* downsample when we reach this index */
 #endif
 } my_prep_controller;
 
-typedef my_prep_controller * my_prep_ptr;
+typedef my_prep_controller *my_prep_ptr;
 
 
 /*
  * Initialize for a processing pass.
  */
 
 METHODDEF(void)
 start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
@@ -131,17 +132,17 @@ pre_process_data (j_compress_ptr cinfo,
                   JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
                   JDIMENSION in_rows_avail,
                   JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
                   JDIMENSION out_row_groups_avail)
 {
   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
   int numrows, ci;
   JDIMENSION inrows;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   while (*in_row_ctr < in_rows_avail &&
          *out_row_group_ctr < out_row_groups_avail) {
     /* Do color conversion to fill the conversion buffer. */
     inrows = in_rows_avail - *in_row_ctr;
     numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
     numrows = (int) MIN((JDIMENSION) numrows, inrows);
     (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
@@ -266,17 +267,17 @@ pre_process_context (j_compress_ptr cinf
  */
 
 LOCAL(void)
 create_context_buffer (j_compress_ptr cinfo)
 {
   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
   int rgroup_height = cinfo->max_v_samp_factor;
   int ci, i;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
   JSAMPARRAY true_buffer, fake_buffer;
 
   /* Grab enough space for fake row pointers for all the components;
    * we need five row groups' worth of pointers for each component.
    */
   fake_buffer = (JSAMPARRAY)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
                                 (cinfo->num_components * 5 * rgroup_height) *
@@ -313,17 +314,17 @@ create_context_buffer (j_compress_ptr ci
  * Initialize preprocessing controller.
  */
 
 GLOBAL(void)
 jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
 {
   my_prep_ptr prep;
   int ci;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   if (need_full_buffer)         /* safety check */
     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
 
   prep = (my_prep_ptr)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
                                 sizeof(my_prep_controller));
   cinfo->prep = (struct jpeg_c_prep_controller *) prep;
--- a/media/libjpeg/jcsample.c
+++ b/media/libjpeg/jcsample.c
@@ -1,17 +1,19 @@
 /*
  * jcsample.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1996, Thomas G. Lane.
  * libjpeg-turbo Modifications:
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright (C) 2014, MIPS Technologies, Inc., California
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2014, MIPS Technologies, Inc., California.
+ * Copyright (C) 2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains downsampling routines.
  *
  * Downsampling input data is counted in "row groups".  A row group
  * is defined to be max_v_samp_factor pixel rows of each component,
  * from which the downsampler produces v_samp_factor sample rows.
  * A single row group is processed in each call to the downsampler module.
  *
@@ -51,30 +53,30 @@
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
 #include "jsimd.h"
 
 
 /* Pointer to routine to downsample a single component */
 typedef void (*downsample1_ptr) (j_compress_ptr cinfo,
-                                 jpeg_component_info * compptr,
+                                 jpeg_component_info *compptr,
                                  JSAMPARRAY input_data,
                                  JSAMPARRAY output_data);
 
 /* Private subobject */
 
 typedef struct {
   struct jpeg_downsampler pub;  /* public fields */
 
   /* Downsampling method pointers, one per component */
   downsample1_ptr methods[MAX_COMPONENTS];
 } my_downsampler;
 
-typedef my_downsampler * my_downsample_ptr;
+typedef my_downsampler *my_downsample_ptr;
 
 
 /*
  * Initialize for a downsampling pass.
  */
 
 METHODDEF(void)
 start_pass_downsample (j_compress_ptr cinfo)
@@ -117,17 +119,17 @@ expand_right_edge (JSAMPARRAY image_data
 
 METHODDEF(void)
 sep_downsample (j_compress_ptr cinfo,
                 JSAMPIMAGE input_buf, JDIMENSION in_row_index,
                 JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
 {
   my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
   int ci;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
   JSAMPARRAY in_ptr, out_ptr;
 
   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
        ci++, compptr++) {
     in_ptr = input_buf[ci] + in_row_index;
     out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
     (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
   }
@@ -137,24 +139,24 @@ sep_downsample (j_compress_ptr cinfo,
 /*
  * Downsample pixel values of a single component.
  * One row group is processed per call.
  * This version handles arbitrary integral sampling ratios, without smoothing.
  * Note that this version is not actually used for customary sampling ratios.
  */
 
 METHODDEF(void)
-int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+int_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
                 JSAMPARRAY input_data, JSAMPARRAY output_data)
 {
   int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
   JDIMENSION outcol, outcol_h;  /* outcol_h == outcol*h_expand */
   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
   JSAMPROW inptr, outptr;
-  INT32 outvalue;
+  JLONG outvalue;
 
   h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
   v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
   numpix = h_expand * v_expand;
   numpix2 = numpix/2;
 
   /* Expand input data enough to let all the output samples be generated
    * by the standard loop.  Special-casing padded output would be more
@@ -167,34 +169,34 @@ int_downsample (j_compress_ptr cinfo, jp
   for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
     outptr = output_data[outrow];
     for (outcol = 0, outcol_h = 0; outcol < output_cols;
          outcol++, outcol_h += h_expand) {
       outvalue = 0;
       for (v = 0; v < v_expand; v++) {
         inptr = input_data[inrow+v] + outcol_h;
         for (h = 0; h < h_expand; h++) {
-          outvalue += (INT32) GETJSAMPLE(*inptr++);
+          outvalue += (JLONG) GETJSAMPLE(*inptr++);
         }
       }
       *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
     }
     inrow += v_expand;
   }
 }
 
 
 /*
  * Downsample pixel values of a single component.
  * This version handles the special case of a full-size component,
  * without smoothing.
  */
 
 METHODDEF(void)
-fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
                      JSAMPARRAY input_data, JSAMPARRAY output_data)
 {
   /* Copy the data */
   jcopy_sample_rows(input_data, 0, output_data, 0,
                     cinfo->max_v_samp_factor, cinfo->image_width);
   /* Edge-expand */
   expand_right_edge(output_data, cinfo->max_v_samp_factor,
                     cinfo->image_width, compptr->width_in_blocks * DCTSIZE);
@@ -209,17 +211,17 @@ fullsize_downsample (j_compress_ptr cinf
  * A note about the "bias" calculations: when rounding fractional values to
  * integer, we do not want to always round 0.5 up to the next integer.
  * If we did that, we'd introduce a noticeable bias towards larger values.
  * Instead, this code is arranged so that 0.5 will be rounded up or down at
  * alternate pixel locations (a simple ordered dither pattern).
  */
 
 METHODDEF(void)
-h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
                  JSAMPARRAY input_data, JSAMPARRAY output_data)
 {
   int outrow;
   JDIMENSION outcol;
   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
   register JSAMPROW inptr, outptr;
   register int bias;
 
@@ -246,17 +248,17 @@ h2v1_downsample (j_compress_ptr cinfo, j
 
 /*
  * Downsample pixel values of a single component.
  * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
  * without smoothing.
  */
 
 METHODDEF(void)
-h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
                  JSAMPARRAY input_data, JSAMPARRAY output_data)
 {
   int inrow, outrow;
   JDIMENSION outcol;
   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
   register JSAMPROW inptr0, inptr1, outptr;
   register int bias;
 
@@ -289,24 +291,24 @@ h2v2_downsample (j_compress_ptr cinfo, j
 
 /*
  * Downsample pixel values of a single component.
  * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
  * with smoothing.  One row of context is required.
  */
 
 METHODDEF(void)
-h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
                         JSAMPARRAY input_data, JSAMPARRAY output_data)
 {
   int inrow, outrow;
   JDIMENSION colctr;
   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
   register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
-  INT32 membersum, neighsum, memberscale, neighscale;
+  JLONG membersum, neighsum, memberscale, neighscale;
 
   /* Expand input data enough to let all the output samples be generated
    * by the standard loop.  Special-casing padded output would be more
    * efficient.
    */
   expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
                     cinfo->image_width, output_cols * 2);
 
@@ -396,17 +398,17 @@ h2v2_smooth_downsample (j_compress_ptr c
 METHODDEF(void)
 fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
                             JSAMPARRAY input_data, JSAMPARRAY output_data)
 {
   int outrow;
   JDIMENSION colctr;
   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
   register JSAMPROW inptr, above_ptr, below_ptr, outptr;
-  INT32 membersum, neighsum, memberscale, neighscale;
+  JLONG membersum, neighsum, memberscale, neighscale;
   int colsum, lastcolsum, nextcolsum;
 
   /* Expand input data enough to let all the output samples be generated
    * by the standard loop.  Special-casing padded output would be more
    * efficient.
    */
   expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
                     cinfo->image_width, output_cols);
@@ -465,17 +467,17 @@ fullsize_smooth_downsample (j_compress_p
  * Note that we must select a routine for each component.
  */
 
 GLOBAL(void)
 jinit_downsampler (j_compress_ptr cinfo)
 {
   my_downsample_ptr downsample;
   int ci;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
   boolean smoothok = TRUE;
 
   downsample = (my_downsample_ptr)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
                                 sizeof(my_downsampler));
   cinfo->downsample = (struct jpeg_downsampler *) downsample;
   downsample->pub.start_pass = start_pass_downsample;
   downsample->pub.downsample = sep_downsample;
--- a/media/libjpeg/jctrans.c
+++ b/media/libjpeg/jctrans.c
@@ -1,49 +1,50 @@
 /*
  * jctrans.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1995-1998, Thomas G. Lane.
  * Modified 2000-2009 by Guido Vollbeding.
  * It was modified by The libjpeg-turbo Project to include only code relevant
  * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains library routines for transcoding compression,
  * that is, writing raw DCT coefficient arrays to an output JPEG file.
  * The routines in jcapimin.c will also be needed by a transcoder.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
 
 
 /* Forward declarations */
 LOCAL(void) transencode_master_selection
-        (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays);
+        (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays);
 LOCAL(void) transencode_coef_controller
-        (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays);
+        (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays);
 
 
 /*
  * Compression initialization for writing raw-coefficient data.
  * Before calling this, all parameters and a data destination must be set up.
  * Call jpeg_finish_compress() to actually write the data.
  *
  * The number of passed virtual arrays must match cinfo->num_components.
  * Note that the virtual arrays need not be filled or even realized at
  * the time write_coefficients is called; indeed, if the virtual arrays
  * were requested from this compression object's memory manager, they
  * typically will be realized during this routine and filled afterwards.
  */
 
 GLOBAL(void)
-jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)
+jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
 {
   if (cinfo->global_state != CSTATE_START)
     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
   /* Mark all tables to be written */
   jpeg_suppress_tables(cinfo, FALSE);
   /* (Re)initialize error mgr and destination modules */
   (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
   (*cinfo->dest->init_destination) (cinfo);
@@ -61,17 +62,17 @@ jpeg_write_coefficients (j_compress_ptr 
  * transcoding.  Parameters that can be varied without loss (such as
  * scan script and Huffman optimization) are left in their default states.
  */
 
 GLOBAL(void)
 jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
                                j_compress_ptr dstinfo)
 {
-  JQUANT_TBL ** qtblptr;
+  JQUANT_TBL **qtblptr;
   jpeg_component_info *incomp, *outcomp;
   JQUANT_TBL *c_quant, *slot_quant;
   int tblno, ci, coefi;
 
   /* Safety check to ensure start_compress not called yet. */
   if (dstinfo->global_state != CSTATE_START)
     ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
   /* Copy fundamental image dimensions */
@@ -160,17 +161,17 @@ jpeg_copy_critical_parameters (j_decompr
 
 /*
  * Master selection of compression modules for transcoding.
  * This substitutes for jcinit.c's initialization of the full compressor.
  */
 
 LOCAL(void)
 transencode_master_selection (j_compress_ptr cinfo,
-                              jvirt_barray_ptr * coef_arrays)
+                              jvirt_barray_ptr *coef_arrays)
 {
   /* Although we don't actually use input_components for transcoding,
    * jcmaster.c's initial_setup will complain if input_components is 0.
    */
   cinfo->input_components = 1;
   /* Initialize master control (includes parameter checking/processing) */
   jinit_c_master_control(cinfo, TRUE /* transcode only */);
 
@@ -222,23 +223,23 @@ typedef struct {
   struct jpeg_c_coef_controller pub; /* public fields */
 
   JDIMENSION iMCU_row_num;      /* iMCU row # within image */
   JDIMENSION mcu_ctr;           /* counts MCUs processed in current row */
   int MCU_vert_offset;          /* counts MCU rows within iMCU row */
   int MCU_rows_per_iMCU_row;    /* number of such rows needed */
 
   /* Virtual block array for each component. */
-  jvirt_barray_ptr * whole_image;
+  jvirt_barray_ptr *whole_image;
 
   /* Workspace for constructing dummy blocks at right/bottom edges. */
   JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU];
 } my_coef_controller;
 
-typedef my_coef_controller * my_coef_ptr;
+typedef my_coef_controller *my_coef_ptr;
 
 
 LOCAL(void)
 start_iMCU_row (j_compress_ptr cinfo)
 /* Reset within-iMCU-row counters for a new row */
 {
   my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
 
@@ -369,17 +370,17 @@ compress_output (j_compress_ptr cinfo, J
  *
  * Each passed coefficient array must be the right size for that
  * coefficient: width_in_blocks wide and height_in_blocks high,
  * with unitheight at least v_samp_factor.
  */
 
 LOCAL(void)
 transencode_coef_controller (j_compress_ptr cinfo,
-                             jvirt_barray_ptr * coef_arrays)
+                             jvirt_barray_ptr *coef_arrays)
 {
   my_coef_ptr coef;
   JBLOCKROW buffer;
   int i;
 
   coef = (my_coef_ptr)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
                                 sizeof(my_coef_controller));
--- a/media/libjpeg/jdapimin.c
+++ b/media/libjpeg/jdapimin.c
@@ -1,31 +1,33 @@
 /*
  * jdapimin.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1998, Thomas G. Lane.
- * It was modified by The libjpeg-turbo Project to include only code relevant
- * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * libjpeg-turbo Modifications:
+ * Copyright (C) 2016, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains application interface code for the decompression half
  * of the JPEG library.  These are the "minimum" API routines that may be
  * needed in either the normal full-decompression case or the
  * transcoding-only case.
  *
  * Most of the routines intended to be called directly by an application
  * are in this file or in jdapistd.c.  But also see jcomapi.c for routines
  * shared by compression and decompression, and jdtrans.c for the transcoding
  * case.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
+#include "jdmaster.h"
 
 
 /*
  * Initialization of a JPEG decompression object.
  * The error manager must already be set up (in case memory manager fails).
  */
 
 GLOBAL(void)
@@ -77,16 +79,24 @@ jpeg_CreateDecompress (j_decompress_ptr 
   cinfo->marker_list = NULL;
   jinit_marker_reader(cinfo);
 
   /* And initialize the overall input controller. */
   jinit_input_controller(cinfo);
 
   /* OK, I'm ready */
   cinfo->global_state = DSTATE_START;
+
+  /* The master struct is used to store extension parameters, so we allocate it
+   * here.
+   */
+  cinfo->master = (struct jpeg_decomp_master *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+                                  sizeof(my_decomp_master));
+  MEMZERO(cinfo->master, sizeof(my_decomp_master));
 }
 
 
 /*
  * Destruction of a JPEG decompression object
  */
 
 GLOBAL(void)
--- a/media/libjpeg/jdapistd.c
+++ b/media/libjpeg/jdapistd.c
@@ -1,31 +1,33 @@
 /*
  * jdapistd.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1996, Thomas G. Lane.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2010, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2010, 2015-2016, D. R. Commander.
+ * Copyright (C) 2015, Google, Inc.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains application interface code for the decompression half
  * of the JPEG library.  These are the "standard" API routines that are
  * used in the normal full-decompression case.  They are not used by a
  * transcoding-only application.  Note that if an application links in
  * jpeg_start_decompress, it will end up linking in the entire decompressor.
  * We thus must separate this file from jdapimin.c to avoid linking the
  * whole decompression library into a transcoder.
  */
 
-#define JPEG_INTERNALS
 #include "jinclude.h"
-#include "jpeglib.h"
-#include "jpegcomp.h"
-
+#include "jdmainct.h"
+#include "jdcoefct.h"
+#include "jdsample.h"
+#include "jmemsys.h"
 
 /* Forward declarations */
 LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo);
 
 
 /*
  * Decompression initialization.
  * jpeg_read_header must be completed before calling this.
@@ -134,16 +136,120 @@ output_pass_setup (j_decompress_ptr cinf
    * jpeg_read_scanlines or jpeg_read_raw_data.
    */
   cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
   return TRUE;
 }
 
 
 /*
+ * Enable partial scanline decompression
+ *
+ * Must be called after jpeg_start_decompress() and before any calls to
+ * jpeg_read_scanlines() or jpeg_skip_scanlines().
+ *
+ * Refer to libjpeg.txt for more information.
+ */
+
+GLOBAL(void)
+jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
+                    JDIMENSION *width)
+{
+  int ci, align, orig_downsampled_width;
+  JDIMENSION input_xoffset;
+  boolean reinit_upsampler = FALSE;
+  jpeg_component_info *compptr;
+
+  if (cinfo->global_state != DSTATE_SCANNING || cinfo->output_scanline != 0)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  if (!xoffset || !width)
+    ERREXIT(cinfo, JERR_BAD_CROP_SPEC);
+
+  /* xoffset and width must fall within the output image dimensions. */
+  if (*width == 0 || *xoffset + *width > cinfo->output_width)
+    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+  /* No need to do anything if the caller wants the entire width. */
+  if (*width == cinfo->output_width)
+    return;
+
+  /* Ensuring the proper alignment of xoffset is tricky.  At minimum, it
+   * must align with an MCU boundary, because:
+   *
+   *   (1) The IDCT is performed in blocks, and it is not feasible to modify
+   *       the algorithm so that it can transform partial blocks.
+   *   (2) Because of the SIMD extensions, any input buffer passed to the
+   *       upsampling and color conversion routines must be aligned to the
+   *       SIMD word size (for instance, 128-bit in the case of SSE2.)  The
+   *       easiest way to accomplish this without copying data is to ensure
+   *       that upsampling and color conversion begin at the start of the
+   *       first MCU column that will be inverse transformed.
+   *
+   * In practice, we actually impose a stricter alignment requirement.  We
+   * require that xoffset be a multiple of the maximum MCU column width of all
+   * of the components (the "iMCU column width.")  This is to simplify the
+   * single-pass decompression case, allowing us to use the same MCU column
+   * width for all of the components.
+   */
+  align = cinfo->_min_DCT_scaled_size * cinfo->max_h_samp_factor;
+
+  /* Adjust xoffset to the nearest iMCU boundary <= the requested value */
+  input_xoffset = *xoffset;
+  *xoffset = (input_xoffset / align) * align;
+
+  /* Adjust the width so that the right edge of the output image is as
+   * requested (only the left edge is altered.)  It is important that calling
+   * programs check this value after this function returns, so that they can
+   * allocate an output buffer with the appropriate size.
+   */
+  *width = *width + input_xoffset - *xoffset;
+  cinfo->output_width = *width;
+
+  /* Set the first and last iMCU columns that we must decompress.  These values
+   * will be used in single-scan decompressions.
+   */
+  cinfo->master->first_iMCU_col =
+    (JDIMENSION) (long) (*xoffset) / (long) align;
+  cinfo->master->last_iMCU_col =
+    (JDIMENSION) jdiv_round_up((long) (*xoffset + cinfo->output_width),
+                               (long) align) - 1;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Set downsampled_width to the new output width. */
+    orig_downsampled_width = compptr->downsampled_width;
+    compptr->downsampled_width =
+      (JDIMENSION) jdiv_round_up((long) (cinfo->output_width *
+                                         compptr->h_samp_factor),
+                                 (long) cinfo->max_h_samp_factor);
+    if (compptr->downsampled_width < 2 && orig_downsampled_width >= 2)
+      reinit_upsampler = TRUE;
+
+    /* Set the first and last iMCU columns that we must decompress.  These
+     * values will be used in multi-scan decompressions.
+     */
+    cinfo->master->first_MCU_col[ci] =
+      (JDIMENSION) (long) (*xoffset * compptr->h_samp_factor) /
+                   (long) align;
+    cinfo->master->last_MCU_col[ci] =
+      (JDIMENSION) jdiv_round_up((long) ((*xoffset + cinfo->output_width) *
+                                         compptr->h_samp_factor),
+                                 (long) align) - 1;
+  }
+
+  if (reinit_upsampler) {
+    cinfo->master->jinit_upsampler_no_alloc = TRUE;
+    jinit_upsampler(cinfo);
+    cinfo->master->jinit_upsampler_no_alloc = FALSE;
+  }
+}
+
+
+/*
  * Read some scanlines of data from the JPEG decompressor.
  *
  * The return value will be the number of lines actually read.
  * This may be less than the number requested in several cases,
  * including bottom of image, data source suspension, and operating
  * modes that emit multiple scanlines at a time.
  *
  * Note: we warn about excess calls to jpeg_read_scanlines() since
@@ -174,16 +280,246 @@ jpeg_read_scanlines (j_decompress_ptr ci
   /* Process some data */
   row_ctr = 0;
   (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
   cinfo->output_scanline += row_ctr;
   return row_ctr;
 }
 
 
+/* Dummy color convert function used by jpeg_skip_scanlines() */
+LOCAL(void)
+noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+              JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
+{
+}
+
+
+/*
+ * In some cases, it is best to call jpeg_read_scanlines() and discard the
+ * output, rather than skipping the scanlines, because this allows us to
+ * maintain the internal state of the context-based upsampler.  In these cases,
+ * we set up and tear down a dummy color converter in order to avoid valgrind
+ * errors and to achieve the best possible performance.
+ */
+
+LOCAL(void)
+read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
+{
+  JDIMENSION n;
+  void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+                         JDIMENSION input_row, JSAMPARRAY output_buf,
+                         int num_rows);
+
+  color_convert = cinfo->cconvert->color_convert;
+  cinfo->cconvert->color_convert = noop_convert;
+
+  for (n = 0; n < num_lines; n++)
+    jpeg_read_scanlines(cinfo, NULL, 1);
+
+  cinfo->cconvert->color_convert = color_convert;
+}
+
+
+/*
+ * Called by jpeg_skip_scanlines().  This partially skips a decompress block by
+ * incrementing the rowgroup counter.
+ */
+
+LOCAL(void)
+increment_simple_rowgroup_ctr (j_decompress_ptr cinfo, JDIMENSION rows)
+{
+  JDIMENSION rows_left;
+  my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+
+  /* Increment the counter to the next row group after the skipped rows. */
+  main_ptr->rowgroup_ctr += rows / cinfo->max_v_samp_factor;
+
+  /* Partially skipping a row group would involve modifying the internal state
+   * of the upsampler, so read the remaining rows into a dummy buffer instead.
+   */
+  rows_left = rows % cinfo->max_v_samp_factor;
+  cinfo->output_scanline += rows - rows_left;
+
+  read_and_discard_scanlines(cinfo, rows_left);
+}
+
+/*
+ * Skips some scanlines of data from the JPEG decompressor.
+ *
+ * The return value will be the number of lines actually skipped.  If skipping
+ * num_lines would move beyond the end of the image, then the actual number of
+ * lines remaining in the image is returned.  Otherwise, the return value will
+ * be equal to num_lines.
+ *
+ * Refer to libjpeg.txt for more information.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
+{
+  my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+  my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+  JDIMENSION i, x;
+  int y;
+  JDIMENSION lines_per_iMCU_row, lines_left_in_iMCU_row, lines_after_iMCU_row;
+  JDIMENSION lines_to_skip, lines_to_read;
+
+  if (cinfo->global_state != DSTATE_SCANNING)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  /* Do not skip past the bottom of the image. */
+  if (cinfo->output_scanline + num_lines >= cinfo->output_height) {
+    cinfo->output_scanline = cinfo->output_height;
+    return cinfo->output_height - cinfo->output_scanline;
+  }
+
+  if (num_lines == 0)
+    return 0;
+
+  lines_per_iMCU_row = cinfo->_min_DCT_scaled_size * cinfo->max_v_samp_factor;
+  lines_left_in_iMCU_row =
+    (lines_per_iMCU_row - (cinfo->output_scanline % lines_per_iMCU_row)) %
+    lines_per_iMCU_row;
+  lines_after_iMCU_row = num_lines - lines_left_in_iMCU_row;
+
+  /* Skip the lines remaining in the current iMCU row.  When upsampling
+   * requires context rows, we need the previous and next rows in order to read
+   * the current row.  This adds some complexity.
+   */
+  if (cinfo->upsample->need_context_rows) {
+    /* If the skipped lines would not move us past the current iMCU row, we
+     * read the lines and ignore them.  There might be a faster way of doing
+     * this, but we are facing increasing complexity for diminishing returns.
+     * The increasing complexity would be a by-product of meddling with the
+     * state machine used to skip context rows.  Near the end of an iMCU row,
+     * the next iMCU row may have already been entropy-decoded.  In this unique
+     * case, we will read the next iMCU row if we cannot skip past it as well.
+     */
+    if ((num_lines < lines_left_in_iMCU_row + 1) ||
+        (lines_left_in_iMCU_row <= 1 && main_ptr->buffer_full &&
+         lines_after_iMCU_row < lines_per_iMCU_row + 1)) {
+      read_and_discard_scanlines(cinfo, num_lines);
+      return num_lines;
+    }
+
+    /* If the next iMCU row has already been entropy-decoded, make sure that
+     * we do not skip too far.
+     */
+    if (lines_left_in_iMCU_row <= 1 && main_ptr->buffer_full) {
+      cinfo->output_scanline += lines_left_in_iMCU_row + lines_per_iMCU_row;
+      lines_after_iMCU_row -= lines_per_iMCU_row;
+    } else {
+      cinfo->output_scanline += lines_left_in_iMCU_row;
+    }
+
+    /* If we have just completed the first block, adjust the buffer pointers */
+    if (main_ptr->iMCU_row_ctr == 0 ||
+        (main_ptr->iMCU_row_ctr == 1 && lines_left_in_iMCU_row > 2))
+      set_wraparound_pointers(cinfo);
+    main_ptr->buffer_full = FALSE;
+    main_ptr->rowgroup_ctr = 0;
+    main_ptr->context_state = CTX_PREPARE_FOR_IMCU;
+    upsample->next_row_out = cinfo->max_v_samp_factor;
+    upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline;
+  }
+
+  /* Skipping is much simpler when context rows are not required. */
+  else {
+    if (num_lines < lines_left_in_iMCU_row) {
+      increment_simple_rowgroup_ctr(cinfo, num_lines);
+      return num_lines;
+    } else {
+      cinfo->output_scanline += lines_left_in_iMCU_row;
+      main_ptr->buffer_full = FALSE;
+      main_ptr->rowgroup_ctr = 0;
+      upsample->next_row_out = cinfo->max_v_samp_factor;
+      upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline;
+    }
+  }
+
+  /* Calculate how many full iMCU rows we can skip. */
+  if (cinfo->upsample->need_context_rows)
+    lines_to_skip = ((lines_after_iMCU_row - 1) / lines_per_iMCU_row) *
+                    lines_per_iMCU_row;
+  else
+    lines_to_skip = (lines_after_iMCU_row / lines_per_iMCU_row) *
+                    lines_per_iMCU_row;
+  /* Calculate the number of lines that remain to be skipped after skipping all
+   * of the full iMCU rows that we can.  We will not read these lines unless we
+   * have to.
+   */
+  lines_to_read = lines_after_iMCU_row - lines_to_skip;
+
+  /* For images requiring multiple scans (progressive, non-interleaved, etc.),
+   * all of the entropy decoding occurs in jpeg_start_decompress(), assuming
+   * that the input data source is non-suspending.  This makes skipping easy.
+   */
+  if (cinfo->inputctl->has_multiple_scans) {
+    if (cinfo->upsample->need_context_rows) {
+      cinfo->output_scanline += lines_to_skip;
+      cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row;
+      main_ptr->iMCU_row_ctr += lines_after_iMCU_row / lines_per_iMCU_row;
+      /* It is complex to properly move to the middle of a context block, so
+       * read the remaining lines instead of skipping them.
+       */
+      read_and_discard_scanlines(cinfo, lines_to_read);
+    } else {
+      cinfo->output_scanline += lines_to_skip;
+      cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row;
+      increment_simple_rowgroup_ctr(cinfo, lines_to_read);
+    }
+    upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline;
+    return num_lines;
+  }
+
+  /* Skip the iMCU rows that we can safely skip. */
+  for (i = 0; i < lines_to_skip; i += lines_per_iMCU_row) {
+    for (y = 0; y < coef->MCU_rows_per_iMCU_row; y++) {
+      for (x = 0; x < cinfo->MCUs_per_row; x++) {
+        /* Calling decode_mcu() with a NULL pointer causes it to discard the
+         * decoded coefficients.  This is ~5% faster for large subsets, but
+         * it's tough to tell a difference for smaller images.
+         */
+        (*cinfo->entropy->decode_mcu) (cinfo, NULL);
+      }
+    }
+    cinfo->input_iMCU_row++;
+    cinfo->output_iMCU_row++;
+    if (cinfo->input_iMCU_row < cinfo->total_iMCU_rows)
+      start_iMCU_row(cinfo);
+    else
+      (*cinfo->inputctl->finish_input_pass) (cinfo);
+  }
+  cinfo->output_scanline += lines_to_skip;
+
+  if (cinfo->upsample->need_context_rows) {
+    /* Context-based upsampling keeps track of iMCU rows. */
+    main_ptr->iMCU_row_ctr += lines_to_skip / lines_per_iMCU_row;
+
+    /* It is complex to properly move to the middle of a context block, so
+     * read the remaining lines instead of skipping them.
+     */
+    read_and_discard_scanlines(cinfo, lines_to_read);
+  } else {
+    increment_simple_rowgroup_ctr(cinfo, lines_to_read);
+  }
+
+  /* Since skipping lines involves skipping the upsampling step, the value of
+   * "rows_to_go" will become invalid unless we set it here.  NOTE: This is a
+   * bit odd, since "rows_to_go" seems to be redundantly keeping track of
+   * output_scanline.
+   */
+  upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline;
+
+  /* Always skip the requested number of lines. */
+  return num_lines;
+}
+
 /*
  * Alternate entry point to read raw data.
  * Processes exactly one iMCU row per call, unless suspended.
  */
 
 GLOBAL(JDIMENSION)
 jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
                     JDIMENSION max_lines)
--- a/media/libjpeg/jdarith.c
+++ b/media/libjpeg/jdarith.c
@@ -1,16 +1,17 @@
 /*
  * jdarith.c
  *
  * This file was part of the Independent JPEG Group's software:
- * Developed 1997-2009 by Guido Vollbeding.
- * It was modified by The libjpeg-turbo Project to include only code relevant
- * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * Developed 1997-2015 by Guido Vollbeding.
+ * libjpeg-turbo Modifications:
+ * Copyright (C) 2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains portable arithmetic entropy decoding routines for JPEG
  * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81).
  *
  * Both sequential and progressive modes are supported in this single module.
  *
  * Suspension is not currently supported in this module.
  */
@@ -20,36 +21,36 @@
 #include "jpeglib.h"
 
 
 /* Expanded entropy decoder object for arithmetic decoding. */
 
 typedef struct {
   struct jpeg_entropy_decoder pub; /* public fields */
 
-  INT32 c;       /* C register, base of coding interval + input bit buffer */
-  INT32 a;               /* A register, normalized size of coding interval */
+  JLONG c;       /* C register, base of coding interval + input bit buffer */
+  JLONG a;               /* A register, normalized size of coding interval */
   int ct;     /* bit shift counter, # of bits left in bit buffer part of C */
                                                          /* init: ct = -16 */
                                                          /* run: ct = 0..7 */
                                                          /* error: ct = -1 */
   int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
   int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */
 
   unsigned int restarts_to_go;  /* MCUs left in this restart interval */
 
   /* Pointers to statistics areas (these workspaces have image lifespan) */
-  unsigned char * dc_stats[NUM_ARITH_TBLS];
-  unsigned char * ac_stats[NUM_ARITH_TBLS];
+  unsigned char *dc_stats[NUM_ARITH_TBLS];
+  unsigned char *ac_stats[NUM_ARITH_TBLS];
 
   /* Statistics bin for coding with fixed probability 0.5 */
   unsigned char fixed_bin[4];
 } arith_entropy_decoder;
 
-typedef arith_entropy_decoder * arith_entropy_ptr;
+typedef arith_entropy_decoder *arith_entropy_ptr;
 
 /* The following two definitions specify the allocation chunk size
  * for the statistics area.
  * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least
  * 49 statistics bins for DC, and 245 statistics bins for AC coding.
  *
  * We use a compact representation with 1 byte per statistics bin,
  * thus the numbers directly represent byte sizes.
@@ -62,17 +63,17 @@ typedef arith_entropy_decoder * arith_en
 #define DC_STAT_BINS 64
 #define AC_STAT_BINS 256
 
 
 LOCAL(int)
 get_byte (j_decompress_ptr cinfo)
 /* Read next input byte; we do not support suspension in this module. */
 {
-  struct jpeg_source_mgr * src = cinfo->src;
+  struct jpeg_source_mgr *src = cinfo->src;
 
   if (src->bytes_in_buffer == 0)
     if (! (*src->fill_input_buffer) (cinfo))
       ERREXIT(cinfo, JERR_CANT_SUSPEND);
   src->bytes_in_buffer--;
   return GETJOCTET(*src->next_input_byte++);
 }
 
@@ -91,30 +92,30 @@ get_byte (j_decompress_ptr cinfo)
  * buffer register C compared to other implementations
  * based on the standards layout & procedures.
  * While it also contains both the actual base of the
  * coding interval (16 bits) and the next-bits buffer,
  * the cut-point between these two parts is floating
  * (instead of fixed) with the bit shift counter CT.
  * Thus, we also need only one (variable instead of
  * fixed size) shift for the LPS/MPS decision, and
- * we can get away with any renormalization update
+ * we can do away with any renormalization update
  * of C (except for new data insertion, of course).
  *
  * I've also introduced a new scheme for accessing
  * the probability estimation state machine table,
  * derived from Markus Kuhn's JBIG implementation.
  */
 
 LOCAL(int)
 arith_decode (j_decompress_ptr cinfo, unsigned char *st)
 {
   register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
   register unsigned char nl, nm;
-  register INT32 qe, temp;
+  register JLONG qe, temp;
   register int sv, data;
 
   /* Renormalization & data input per section D.2.6 */
   while (e->a < 0x8000L) {
     if (--e->ct < 0) {
       /* Need to fetch next data byte */
       if (cinfo->unread_marker)
         data = 0;               /* stuff zero data */
@@ -188,32 +189,32 @@ arith_decode (j_decompress_ptr cinfo, un
  * Check for a restart marker & resynchronize decoder.
  */
 
 LOCAL(void)
 process_restart (j_decompress_ptr cinfo)
 {
   arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
   int ci;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   /* Advance past the RSTn marker */
   if (! (*cinfo->marker->read_restart_marker) (cinfo))
     ERREXIT(cinfo, JERR_CANT_SUSPEND);
 
   /* Re-initialize statistics areas */
   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
     compptr = cinfo->cur_comp_info[ci];
-    if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
+    if (!cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
       MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS);
       /* Reset DC predictions to 0 */
       entropy->last_dc_val[ci] = 0;
       entropy->dc_context[ci] = 0;
     }
-    if (! cinfo->progressive_mode || cinfo->Ss) {
+    if (!cinfo->progressive_mode || cinfo->Ss) {
       MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS);
     }
   }
 
   /* Reset arithmetic decoding variables */
   entropy->c = 0;
   entropy->a = 0;
   entropy->ct = -16;    /* force reading 2 initial bytes to fill C */
@@ -493,17 +494,17 @@ decode_mcu_AC_refine (j_decompress_ptr c
 /*
  * Decode one MCU's worth of arithmetic-compressed coefficients.
  */
 
 METHODDEF(boolean)
 decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
 {
   arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
   JBLOCKROW block;
   unsigned char *st;
   int blkn, ci, tbl, sign, k;
   int v, m;
 
   /* Process restart marker if needed */
   if (cinfo->restart_interval) {
     if (entropy->restarts_to_go == 0)
@@ -511,17 +512,17 @@ decode_mcu (j_decompress_ptr cinfo, JBLO
     entropy->restarts_to_go--;
   }
 
   if (entropy->ct == -1) return TRUE;   /* if error do nothing */
 
   /* Outer loop handles each block in the MCU */
 
   for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
-    block = MCU_data[blkn];
+    block = MCU_data ? MCU_data[blkn] : NULL;
     ci = cinfo->MCU_membership[blkn];
     compptr = cinfo->cur_comp_info[ci];
 
     /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */
 
     tbl = compptr->dc_tbl_no;
 
     /* Table F.4: Point to statistics bin S0 for DC coefficient coding */
@@ -558,17 +559,18 @@ decode_mcu (j_decompress_ptr cinfo, JBLO
       /* Figure F.24: Decoding the magnitude bit pattern of v */
       st += 14;
       while (m >>= 1)
         if (arith_decode(cinfo, st)) v |= m;
       v += 1; if (sign) v = -v;
       entropy->last_dc_val[ci] += v;
     }
 
-    (*block)[0] = (JCOEF) entropy->last_dc_val[ci];
+    if (block)
+      (*block)[0] = (JCOEF) entropy->last_dc_val[ci];
 
     /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */
 
     tbl = compptr->ac_tbl_no;
 
     /* Figure F.20: Decode_AC_coefficients */
     for (k = 1; k <= DCTSIZE2 - 1; k++) {
       st = entropy->ac_stats[tbl] + 3 * (k - 1);
@@ -602,34 +604,35 @@ decode_mcu (j_decompress_ptr cinfo, JBLO
         }
       }
       v = m;
       /* Figure F.24: Decoding the magnitude bit pattern of v */
       st += 14;
       while (m >>= 1)
         if (arith_decode(cinfo, st)) v |= m;
       v += 1; if (sign) v = -v;
-      (*block)[jpeg_natural_order[k]] = (JCOEF) v;
+      if (block)
+        (*block)[jpeg_natural_order[k]] = (JCOEF) v;
     }
   }
 
   return TRUE;
 }
 
 
 /*
  * Initialize for an arithmetic-compressed scan.
  */
 
 METHODDEF(void)
 start_pass (j_decompress_ptr cinfo)
 {
   arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
   int ci, tbl;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   if (cinfo->progressive_mode) {
     /* Validate progressive scan parameters */
     if (cinfo->Ss == 0) {
       if (cinfo->Se != 0)
         goto bad;
     } else {
       /* need not check Ss/Se < 0 since they came from unsigned bytes */
@@ -686,29 +689,29 @@ start_pass (j_decompress_ptr cinfo)
       WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
     /* Select MCU decoding routine */
     entropy->pub.decode_mcu = decode_mcu;
   }
 
   /* Allocate & initialize requested statistics areas */
   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
     compptr = cinfo->cur_comp_info[ci];
-    if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
+    if (!cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
       tbl = compptr->dc_tbl_no;
       if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
         ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
       if (entropy->dc_stats[tbl] == NULL)
         entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
           ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS);
       MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS);
       /* Initialize DC predictions to 0 */
       entropy->last_dc_val[ci] = 0;
       entropy->dc_context[ci] = 0;
     }
-    if (! cinfo->progressive_mode || cinfo->Ss) {
+    if (!cinfo->progressive_mode || cinfo->Ss) {
       tbl = compptr->ac_tbl_no;
       if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
         ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
       if (entropy->ac_stats[tbl] == NULL)
         entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
           ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS);
       MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS);
     }
--- a/media/libjpeg/jdatadst.c
+++ b/media/libjpeg/jdatadst.c
@@ -1,66 +1,67 @@
 /*
  * jdatadst.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1996, Thomas G. Lane.
  * Modified 2009-2012 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2013, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2013, 2016, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains compression data destination routines for the case of
  * emitting JPEG data to memory or to a file (or any stdio stream).
  * While these routines are sufficient for most applications,
  * some will want to use a different destination manager.
  * IMPORTANT: we assume that fwrite() will correctly transcribe an array of
  * JOCTETs into 8-bit-wide elements on external storage.  If char is wider
  * than 8 bits on your machine, you may need to do some tweaking.
  */
 
 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */
 #include "jinclude.h"
 #include "jpeglib.h"
 #include "jerror.h"
 
 #ifndef HAVE_STDLIB_H           /* <stdlib.h> should declare malloc(),free() */
-extern void * malloc (size_t size);
+extern void *malloc (size_t size);
 extern void free (void *ptr);
 #endif
 
 
 /* Expanded data destination object for stdio output */
 
 typedef struct {
   struct jpeg_destination_mgr pub; /* public fields */
 
-  FILE * outfile;               /* target stream */
-  JOCTET * buffer;              /* start of buffer */
+  FILE *outfile;                /* target stream */
+  JOCTET *buffer;               /* start of buffer */
 } my_destination_mgr;
 
-typedef my_destination_mgr * my_dest_ptr;
+typedef my_destination_mgr *my_dest_ptr;
 
 #define OUTPUT_BUF_SIZE  4096   /* choose an efficiently fwrite'able size */
 
 
 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
 /* Expanded data destination object for memory output */
 
 typedef struct {
   struct jpeg_destination_mgr pub; /* public fields */
 
-  unsigned char ** outbuffer;   /* target buffer */
-  unsigned long * outsize;
-  unsigned char * newbuffer;    /* newly allocated buffer */
-  JOCTET * buffer;              /* start of buffer */
+  unsigned char **outbuffer;    /* target buffer */
+  unsigned long *outsize;
+  unsigned char *newbuffer;     /* newly allocated buffer */
+  JOCTET *buffer;               /* start of buffer */
   size_t bufsize;
 } my_mem_destination_mgr;
 
-typedef my_mem_destination_mgr * my_mem_dest_ptr;
+typedef my_mem_destination_mgr *my_mem_dest_ptr;
 #endif
 
 
 /*
  * Initialize destination --- called by jpeg_start_compress
  * before any data is actually written.
  */
 
@@ -125,17 +126,17 @@ empty_output_buffer (j_compress_ptr cinf
   return TRUE;
 }
 
 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
 METHODDEF(boolean)
 empty_mem_output_buffer (j_compress_ptr cinfo)
 {
   size_t nextsize;
-  JOCTET * nextbuffer;
+  JOCTET *nextbuffer;
   my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;
 
   /* Try to allocate new buffer with double size */
   nextsize = dest->bufsize * 2;
   nextbuffer = (JOCTET *) malloc(nextsize);
 
   if (nextbuffer == NULL)
     ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
@@ -198,30 +199,35 @@ term_mem_destination (j_compress_ptr cin
 
 /*
  * Prepare for output to a stdio stream.
  * The caller must have already opened the stream, and is responsible
  * for closing it after finishing compression.
  */
 
 GLOBAL(void)
-jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
+jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
 {
   my_dest_ptr dest;
 
   /* The destination object is made permanent so that multiple JPEG images
    * can be written to the same file without re-executing jpeg_stdio_dest.
-   * This makes it dangerous to use this manager and a different destination
-   * manager serially with the same JPEG object, because their private object
-   * sizes may be different.  Caveat programmer.
    */
   if (cinfo->dest == NULL) {    /* first time for this JPEG object? */
     cinfo->dest = (struct jpeg_destination_mgr *)
       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
                                   sizeof(my_destination_mgr));
+  } else if (cinfo->dest->init_destination != init_destination) {
+    /* It is unsafe to reuse the existing destination manager unless it was
+     * created by this function.  Otherwise, there is no guarantee that the
+     * opaque structure is the right size.  Note that we could just create a
+     * new structure, but the old structure would not be freed until
+     * jpeg_destroy_compress() was called.
+     */
+    ERREXIT(cinfo, JERR_BUFFER_SIZE);
   }
 
   dest = (my_dest_ptr) cinfo->dest;
   dest->pub.init_destination = init_destination;
   dest->pub.empty_output_buffer = empty_output_buffer;
   dest->pub.term_destination = term_destination;
   dest->outfile = outfile;
 }
@@ -232,34 +238,42 @@ jpeg_stdio_dest (j_compress_ptr cinfo, F
  * Prepare for output to a memory buffer.
  * The caller may supply an own initial buffer with appropriate size.
  * Otherwise, or when the actual data output exceeds the given size,
  * the library adapts the buffer size as necessary.
  * The standard library functions malloc/free are used for allocating
  * larger memory, so the buffer is available to the application after
  * finishing compression, and then the application is responsible for
  * freeing the requested memory.
+ * Note:  An initial buffer supplied by the caller is expected to be
+ * managed by the application.  The library does not free such buffer
+ * when allocating a larger buffer.
  */
 
 GLOBAL(void)
 jpeg_mem_dest (j_compress_ptr cinfo,
-               unsigned char ** outbuffer, unsigned long * outsize)
+               unsigned char **outbuffer, unsigned long *outsize)
 {
   my_mem_dest_ptr dest;
 
   if (outbuffer == NULL || outsize == NULL)     /* sanity check */
     ERREXIT(cinfo, JERR_BUFFER_SIZE);
 
   /* The destination object is made permanent so that multiple JPEG images
    * can be written to the same buffer without re-executing jpeg_mem_dest.
    */
   if (cinfo->dest == NULL) {    /* first time for this JPEG object? */
     cinfo->dest = (struct jpeg_destination_mgr *)
       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
                                   sizeof(my_mem_destination_mgr));
+  } else if (cinfo->dest->init_destination != init_mem_destination) {
+    /* It is unsafe to reuse the existing destination manager unless it was
+     * created by this function.
+     */
+    ERREXIT(cinfo, JERR_BUFFER_SIZE);
   }
 
   dest = (my_mem_dest_ptr) cinfo->dest;
   dest->pub.init_destination = init_mem_destination;
   dest->pub.empty_output_buffer = empty_mem_output_buffer;
   dest->pub.term_destination = term_mem_destination;
   dest->outbuffer = outbuffer;
   dest->outsize = outsize;
--- a/media/libjpeg/jdatasrc.c
+++ b/media/libjpeg/jdatasrc.c
@@ -1,17 +1,18 @@
 /*
  * jdatasrc.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1996, Thomas G. Lane.
  * Modified 2009-2011 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2013, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2013, 2016, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains decompression data source routines for the case of
  * reading JPEG data from memory or from a file (or any stdio stream).
  * While these routines are sufficient for most applications,
  * some will want to use a different source manager.
  * IMPORTANT: we assume that fread() will correctly transcribe an array of
  * JOCTETs from 8-bit-wide elements on external storage.  If char is wider
  * than 8 bits on your machine, you may need to do some tweaking.
@@ -23,22 +24,22 @@
 #include "jerror.h"
 
 
 /* Expanded data source object for stdio input */
 
 typedef struct {
   struct jpeg_source_mgr pub;   /* public fields */
 
-  FILE * infile;                /* source stream */
-  JOCTET * buffer;              /* start of buffer */
+  FILE *infile;                 /* source stream */
+  JOCTET *buffer;               /* start of buffer */
   boolean start_of_file;        /* have we gotten any data yet? */
 } my_source_mgr;
 
-typedef my_source_mgr * my_src_ptr;
+typedef my_source_mgr *my_src_ptr;
 
 #define INPUT_BUF_SIZE  4096    /* choose an efficiently fread'able size */
 
 
 /*
  * Initialize source --- called by jpeg_read_header
  * before any data is actually read.
  */
@@ -156,17 +157,17 @@ fill_mem_input_buffer (j_decompress_ptr 
  * that the next read will cause a fill_input_buffer call that can suspend.
  * Arranging for additional bytes to be discarded before reloading the input
  * buffer is the application writer's problem.
  */
 
 METHODDEF(void)
 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
 {
-  struct jpeg_source_mgr * src = cinfo->src;
+  struct jpeg_source_mgr *src = cinfo->src;
 
   /* Just a dumb implementation for now.  Could use fseek() except
    * it doesn't work on pipes.  Not clear that being smart is worth
    * any trouble anyway --- large skips are infrequent.
    */
   if (num_bytes > 0) {
     while (num_bytes > (long) src->bytes_in_buffer) {
       num_bytes -= (long) src->bytes_in_buffer;
@@ -208,35 +209,41 @@ term_source (j_decompress_ptr cinfo)
 
 /*
  * Prepare for input from a stdio stream.
  * The caller must have already opened the stream, and is responsible
  * for closing it after finishing decompression.
  */
 
 GLOBAL(void)
-jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
+jpeg_stdio_src (j_decompress_ptr cinfo, FILE *infile)
 {
   my_src_ptr src;
 
   /* The source object and input buffer are made permanent so that a series
    * of JPEG images can be read from the same file by calling jpeg_stdio_src
    * only before the first one.  (If we discarded the buffer at the end of
    * one image, we'd likely lose the start of the next one.)
-   * This makes it unsafe to use this manager and a different source
-   * manager serially with the same JPEG object.  Caveat programmer.
    */
   if (cinfo->src == NULL) {     /* first time for this JPEG object? */
     cinfo->src = (struct jpeg_source_mgr *)
       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
                                   sizeof(my_source_mgr));
     src = (my_src_ptr) cinfo->src;
     src->buffer = (JOCTET *)
       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
                                   INPUT_BUF_SIZE * sizeof(JOCTET));
+  } else if (cinfo->src->init_source != init_source) {
+    /* It is unsafe to reuse the existing source manager unless it was created
+     * by this function.  Otherwise, there is no guarantee that the opaque
+     * structure is the right size.  Note that we could just create a new
+     * structure, but the old structure would not be freed until
+     * jpeg_destroy_decompress() was called.
+     */
+    ERREXIT(cinfo, JERR_BUFFER_SIZE);
   }
 
   src = (my_src_ptr) cinfo->src;
   src->pub.init_source = init_source;
   src->pub.fill_input_buffer = fill_input_buffer;
   src->pub.skip_input_data = skip_input_data;
   src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
   src->pub.term_source = term_source;
@@ -249,35 +256,40 @@ jpeg_stdio_src (j_decompress_ptr cinfo, 
 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
 /*
  * Prepare for input from a supplied memory buffer.
  * The buffer must contain the whole JPEG data.
  */
 
 GLOBAL(void)
 jpeg_mem_src (j_decompress_ptr cinfo,
-              unsigned char * inbuffer, unsigned long insize)
+              const unsigned char *inbuffer, unsigned long insize)
 {
-  struct jpeg_source_mgr * src;
+  struct jpeg_source_mgr *src;
 
   if (inbuffer == NULL || insize == 0)  /* Treat empty input as fatal error */
     ERREXIT(cinfo, JERR_INPUT_EMPTY);
 
   /* The source object is made permanent so that a series of JPEG images
    * can be read from the same buffer by calling jpeg_mem_src only before
    * the first one.
    */
   if (cinfo->src == NULL) {     /* first time for this JPEG object? */
     cinfo->src = (struct jpeg_source_mgr *)
       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
                                   sizeof(struct jpeg_source_mgr));
+  } else if (cinfo->src->init_source != init_mem_source) {
+    /* It is unsafe to reuse the existing source manager unless it was created
+     * by this function.
+     */
+    ERREXIT(cinfo, JERR_BUFFER_SIZE);
   }
 
   src = cinfo->src;
   src->init_source = init_mem_source;
   src->fill_input_buffer = fill_mem_input_buffer;
   src->skip_input_data = skip_input_data;
   src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
   src->term_source = term_source;
   src->bytes_in_buffer = (size_t) insize;
-  src->next_input_byte = (JOCTET *) inbuffer;
+  src->next_input_byte = (const JOCTET *) inbuffer;
 }
 #endif
--- a/media/libjpeg/jdcoefct.c
+++ b/media/libjpeg/jdcoefct.c
@@ -1,112 +1,48 @@
 /*
  * jdcoefct.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1997, Thomas G. Lane.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2010, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright (C) 2010, 2015-2016, D. R. Commander.
+ * Copyright (C) 2015, Google, Inc.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains the coefficient buffer controller for decompression.
  * This controller is the top level of the JPEG decompressor proper.
  * The coefficient buffer lies between entropy decoding and inverse-DCT steps.
  *
  * In buffered-image mode, this controller is the interface between
  * input-oriented processing and output-oriented processing.
  * Also, the input side (only) is used when reading a file for transcoding.
  */
 
-#define JPEG_INTERNALS
 #include "jinclude.h"
-#include "jpeglib.h"
+#include "jdcoefct.h"
 #include "jpegcomp.h"
 
-/* Block smoothing is only applicable for progressive JPEG, so: */
-#ifndef D_PROGRESSIVE_SUPPORTED
-#undef BLOCK_SMOOTHING_SUPPORTED
-#endif
-
-/* Private buffer controller object */
-
-typedef struct {
-  struct jpeg_d_coef_controller pub; /* public fields */
-
-  /* These variables keep track of the current location of the input side. */
-  /* cinfo->input_iMCU_row is also used for this. */
-  JDIMENSION MCU_ctr;           /* counts MCUs processed in current row */
-  int MCU_vert_offset;          /* counts MCU rows within iMCU row */
-  int MCU_rows_per_iMCU_row;    /* number of such rows needed */
-
-  /* The output side's location is represented by cinfo->output_iMCU_row. */
-
-  /* In single-pass modes, it's sufficient to buffer just one MCU.
-   * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
-   * and let the entropy decoder write into that workspace each time.
-   * In multi-pass modes, this array points to the current MCU's blocks
-   * within the virtual arrays; it is used only by the input side.
-   */
-  JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
-
-  /* Temporary workspace for one MCU */
-  JCOEF * workspace;
-
-#ifdef D_MULTISCAN_FILES_SUPPORTED
-  /* In multi-pass modes, we need a virtual block array for each component. */
-  jvirt_barray_ptr whole_image[MAX_COMPONENTS];
-#endif
-
-#ifdef BLOCK_SMOOTHING_SUPPORTED
-  /* When doing block smoothing, we latch coefficient Al values here */
-  int * coef_bits_latch;
-#define SAVED_COEFS  6          /* we save coef_bits[0..5] */
-#endif
-} my_coef_controller;
-
-typedef my_coef_controller * my_coef_ptr;
 
 /* Forward declarations */
 METHODDEF(int) decompress_onepass
         (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
 #ifdef D_MULTISCAN_FILES_SUPPORTED
 METHODDEF(int) decompress_data
         (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
 #endif
 #ifdef BLOCK_SMOOTHING_SUPPORTED
 LOCAL(boolean) smoothing_ok (j_decompress_ptr cinfo);
 METHODDEF(int) decompress_smooth_data
         (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
 #endif
 
 
-LOCAL(void)
-start_iMCU_row (j_decompress_ptr cinfo)
-/* Reset within-iMCU-row counters for a new row (input side) */
-{
-  my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
-
-  /* In an interleaved scan, an MCU row is the same as an iMCU row.
-   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
-   * But at the bottom of the image, process only what's left.
-   */
-  if (cinfo->comps_in_scan > 1) {
-    coef->MCU_rows_per_iMCU_row = 1;
-  } else {
-    if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
-      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
-    else
-      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
-  }
-
-  coef->MCU_ctr = 0;
-  coef->MCU_vert_offset = 0;
-}
-
-
 /*
  * Initialize for an input processing pass.
  */
 
 METHODDEF(void)
 start_input_pass (j_decompress_ptr cinfo)
 {
   cinfo->input_iMCU_row = 0;
@@ -168,48 +104,56 @@ decompress_onepass (j_decompress_ptr cin
       jzero_far((void *) coef->MCU_buffer[0],
                 (size_t) (cinfo->blocks_in_MCU * sizeof(JBLOCK)));
       if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
         /* Suspension forced; update state counters and exit */
         coef->MCU_vert_offset = yoffset;
         coef->MCU_ctr = MCU_col_num;
         return JPEG_SUSPENDED;
       }
-      /* Determine where data should go in output_buf and do the IDCT thing.
-       * We skip dummy blocks at the right and bottom edges (but blkn gets
-       * incremented past them!).  Note the inner loop relies on having
-       * allocated the MCU_buffer[] blocks sequentially.
+
+      /* Only perform the IDCT on blocks that are contained within the desired
+       * cropping region.
        */
-      blkn = 0;                 /* index of current DCT block within MCU */
-      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
-        compptr = cinfo->cur_comp_info[ci];
-        /* Don't bother to IDCT an uninteresting component. */
-        if (! compptr->component_needed) {
-          blkn += compptr->MCU_blocks;
-          continue;
-        }
-        inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
-        useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
-                                                    : compptr->last_col_width;
-        output_ptr = output_buf[compptr->component_index] +
-          yoffset * compptr->_DCT_scaled_size;
-        start_col = MCU_col_num * compptr->MCU_sample_width;
-        for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
-          if (cinfo->input_iMCU_row < last_iMCU_row ||
-              yoffset+yindex < compptr->last_row_height) {
-            output_col = start_col;
-            for (xindex = 0; xindex < useful_width; xindex++) {
-              (*inverse_DCT) (cinfo, compptr,
-                              (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
-                              output_ptr, output_col);
-              output_col += compptr->_DCT_scaled_size;
+      if (MCU_col_num >= cinfo->master->first_iMCU_col &&
+          MCU_col_num <= cinfo->master->last_iMCU_col) {
+        /* Determine where data should go in output_buf and do the IDCT thing.
+         * We skip dummy blocks at the right and bottom edges (but blkn gets
+         * incremented past them!).  Note the inner loop relies on having
+         * allocated the MCU_buffer[] blocks sequentially.
+         */
+        blkn = 0;                 /* index of current DCT block within MCU */
+        for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+          compptr = cinfo->cur_comp_info[ci];
+          /* Don't bother to IDCT an uninteresting component. */
+          if (! compptr->component_needed) {
+            blkn += compptr->MCU_blocks;
+            continue;
+          }
+          inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
+          useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+                                                      : compptr->last_col_width;
+          output_ptr = output_buf[compptr->component_index] +
+            yoffset * compptr->_DCT_scaled_size;
+          start_col = (MCU_col_num - cinfo->master->first_iMCU_col) *
+              compptr->MCU_sample_width;
+          for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+            if (cinfo->input_iMCU_row < last_iMCU_row ||
+                yoffset+yindex < compptr->last_row_height) {
+              output_col = start_col;
+              for (xindex = 0; xindex < useful_width; xindex++) {
+                (*inverse_DCT) (cinfo, compptr,
+                                (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
+                                output_ptr, output_col);
+                output_col += compptr->_DCT_scaled_size;
+              }
             }
+            blkn += compptr->MCU_width;
+            output_ptr += compptr->_DCT_scaled_size;
           }
-          blkn += compptr->MCU_width;
-          output_ptr += compptr->_DCT_scaled_size;
         }
       }
     }
     /* Completed an MCU row, but perhaps not an iMCU row */
     coef->MCU_ctr = 0;
   }
   /* Completed the iMCU row, advance counters for next one */
   cinfo->output_iMCU_row++;
@@ -354,19 +298,20 @@ decompress_data (j_decompress_ptr cinfo,
       /* NB: can't use last_row_height here; it is input-side-dependent! */
       block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
       if (block_rows == 0) block_rows = compptr->v_samp_factor;
     }
     inverse_DCT = cinfo->idct->inverse_DCT[ci];
     output_ptr = output_buf[ci];
     /* Loop over all DCT blocks to be processed. */
     for (block_row = 0; block_row < block_rows; block_row++) {
-      buffer_ptr = buffer[block_row];
+      buffer_ptr = buffer[block_row] + cinfo->master->first_MCU_col[ci];
       output_col = 0;
-      for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
+      for (block_num = cinfo->master->first_MCU_col[ci];
+           block_num <= cinfo->master->last_MCU_col[ci]; block_num++) {
         (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
                         output_ptr, output_col);
         buffer_ptr++;
         output_col += compptr->_DCT_scaled_size;
       }
       output_ptr += compptr->_DCT_scaled_size;
     }
   }
@@ -406,19 +351,19 @@ decompress_data (j_decompress_ptr cinfo,
 
 LOCAL(boolean)
 smoothing_ok (j_decompress_ptr cinfo)
 {
   my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
   boolean smoothing_useful = FALSE;
   int ci, coefi;
   jpeg_component_info *compptr;
-  JQUANT_TBL * qtable;
-  int * coef_bits;
-  int * coef_bits_latch;
+  JQUANT_TBL *qtable;
+  int *coef_bits;
+  int *coef_bits_latch;
 
   if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
     return FALSE;
 
   /* Allocate latch area if not already done */
   if (coef->coef_bits_latch == NULL)
     coef->coef_bits_latch = (int *)
       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
@@ -469,20 +414,20 @@ decompress_smooth_data (j_decompress_ptr
   int ci, block_row, block_rows, access_rows;
   JBLOCKARRAY buffer;
   JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
   JSAMPARRAY output_ptr;
   JDIMENSION output_col;
   jpeg_component_info *compptr;
   inverse_DCT_method_ptr inverse_DCT;
   boolean first_row, last_row;
-  JCOEF * workspace;
+  JCOEF *workspace;
   int *coef_bits;
   JQUANT_TBL *quanttbl;
-  INT32 Q00,Q01,Q02,Q10,Q11,Q20, num;
+  JLONG Q00,Q01,Q02,Q10,Q11,Q20, num;
   int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
   int Al, pred;
 
   /* Keep a local variable to avoid looking it up more than once */
   workspace = coef->workspace;
 
   /* Force some input to be done if we are getting ahead of the input. */
   while (cinfo->input_scan_number <= cinfo->output_scan_number &&
@@ -542,34 +487,35 @@ decompress_smooth_data (j_decompress_ptr
     Q10 = quanttbl->quantval[Q10_POS];
     Q20 = quanttbl->quantval[Q20_POS];
     Q11 = quanttbl->quantval[Q11_POS];
     Q02 = quanttbl->quantval[Q02_POS];
     inverse_DCT = cinfo->idct->inverse_DCT[ci];
     output_ptr = output_buf[ci];
     /* Loop over all DCT blocks to be processed. */
     for (block_row = 0; block_row < block_rows; block_row++) {
-      buffer_ptr = buffer[block_row];
+      buffer_ptr = buffer[block_row] + cinfo->master->first_MCU_col[ci];
       if (first_row && block_row == 0)
         prev_block_row = buffer_ptr;
       else
         prev_block_row = buffer[block_row-1];
       if (last_row && block_row == block_rows-1)
         next_block_row = buffer_ptr;
       else
         next_block_row = buffer[block_row+1];
       /* We fetch the surrounding DC values using a sliding-register approach.
        * Initialize all nine here so as to do the right thing on narrow pics.
        */
       DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
       DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
       DC7 = DC8 = DC9 = (int) next_block_row[0][0];
       output_col = 0;
       last_block_column = compptr->width_in_blocks - 1;
-      for (block_num = 0; block_num <= last_block_column; block_num++) {
+      for (block_num = cinfo->master->first_MCU_col[ci];
+           block_num <= cinfo->master->last_MCU_col[ci]; block_num++) {
         /* Fetch current DCT block into workspace so we can modify it. */
         jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
         /* Update DC values */
         if (block_num < last_block_column) {
           DC3 = (int) prev_block_row[1][0];
           DC6 = (int) buffer_ptr[1][0];
           DC9 = (int) next_block_row[1][0];
         }
new file mode 100644
--- /dev/null
+++ b/media/libjpeg/jdcoefct.h
@@ -0,0 +1,82 @@
+/*
+ * jdcoefct.h
+ *
+ * This file was part of the Independent JPEG Group's software:
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * libjpeg-turbo Modifications:
+ * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
+ */
+
+#define JPEG_INTERNALS
+#include "jpeglib.h"
+
+
+/* Block smoothing is only applicable for progressive JPEG, so: */
+#ifndef D_PROGRESSIVE_SUPPORTED
+#undef BLOCK_SMOOTHING_SUPPORTED
+#endif
+
+
+/* Private buffer controller object */
+
+typedef struct {
+  struct jpeg_d_coef_controller pub; /* public fields */
+
+  /* These variables keep track of the current location of the input side. */
+  /* cinfo->input_iMCU_row is also used for this. */
+  JDIMENSION MCU_ctr;           /* counts MCUs processed in current row */
+  int MCU_vert_offset;          /* counts MCU rows within iMCU row */
+  int MCU_rows_per_iMCU_row;    /* number of such rows needed */
+
+  /* The output side's location is represented by cinfo->output_iMCU_row. */
+
+  /* In single-pass modes, it's sufficient to buffer just one MCU.
+   * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
+   * and let the entropy decoder write into that workspace each time.
+   * In multi-pass modes, this array points to the current MCU's blocks
+   * within the virtual arrays; it is used only by the input side.
+   */
+  JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
+
+  /* Temporary workspace for one MCU */
+  JCOEF *workspace;
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+  /* In multi-pass modes, we need a virtual block array for each component. */
+  jvirt_barray_ptr whole_image[MAX_COMPONENTS];
+#endif
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  /* When doing block smoothing, we latch coefficient Al values here */
+  int *coef_bits_latch;
+#define SAVED_COEFS  6          /* we save coef_bits[0..5] */
+#endif
+} my_coef_controller;
+
+typedef my_coef_controller *my_coef_ptr;
+
+
+LOCAL(void)
+start_iMCU_row (j_decompress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row (input side) */
+{
+  my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+  /* In an interleaved scan, an MCU row is the same as an iMCU row.
+   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+   * But at the bottom of the image, process only what's left.
+   */
+  if (cinfo->comps_in_scan > 1) {
+    coef->MCU_rows_per_iMCU_row = 1;
+  } else {
+    if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
+      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+    else
+      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+  }
+
+  coef->MCU_ctr = 0;
+  coef->MCU_vert_offset = 0;
+}
--- a/media/libjpeg/jdcol565.c
+++ b/media/libjpeg/jdcol565.c
@@ -1,17 +1,18 @@
 /*
  * jdcol565.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * Modifications:
  * Copyright (C) 2013, Linaro Limited.
- * Copyright (C) 2014, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2014-2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains output colorspace conversion routines.
  */
 
 /* This file is included by jdcolor.c */
 
 
 INLINE
@@ -25,39 +26,39 @@ ycc_rgb565_convert_internal (j_decompres
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->output_width;
   /* copy these pointers into registers if possible */
   register JSAMPLE * range_limit = cinfo->sample_range_limit;
   register int * Crrtab = cconvert->Cr_r_tab;
   register int * Cbbtab = cconvert->Cb_b_tab;
-  register INT32 * Crgtab = cconvert->Cr_g_tab;
-  register INT32 * Cbgtab = cconvert->Cb_g_tab;
+  register JLONG * Crgtab = cconvert->Cr_g_tab;
+  register JLONG * Cbgtab = cconvert->Cb_g_tab;
   SHIFT_TEMPS
 
   while (--num_rows >= 0) {
-    INT32 rgb;
+    JLONG rgb;
     unsigned int r, g, b;
     inptr0 = input_buf[0][input_row];
     inptr1 = input_buf[1][input_row];
     inptr2 = input_buf[2][input_row];
     input_row++;
     outptr = *output_buf++;
 
     if (PACK_NEED_ALIGNMENT(outptr)) {
       y  = GETJSAMPLE(*inptr0++);
       cb = GETJSAMPLE(*inptr1++);
       cr = GETJSAMPLE(*inptr2++);
       r = range_limit[y + Crrtab[cr]];
       g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
                                             SCALEBITS))];
       b = range_limit[y + Cbbtab[cb]];
       rgb = PACK_SHORT_565(r, g, b);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
       outptr += 2;
       num_cols--;
     }
     for (col = 0; col < (num_cols >> 1); col++) {
       y  = GETJSAMPLE(*inptr0++);
       cb = GETJSAMPLE(*inptr1++);
       cr = GETJSAMPLE(*inptr2++);
       r = range_limit[y + Crrtab[cr]];
@@ -82,17 +83,17 @@ ycc_rgb565_convert_internal (j_decompres
       y  = GETJSAMPLE(*inptr0);
       cb = GETJSAMPLE(*inptr1);
       cr = GETJSAMPLE(*inptr2);
       r = range_limit[y + Crrtab[cr]];
       g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
                                             SCALEBITS))];
       b = range_limit[y + Cbbtab[cb]];
       rgb = PACK_SHORT_565(r, g, b);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
     }
   }
 }
 
 
 INLINE
 LOCAL(void)
 ycc_rgb565D_convert_internal (j_decompress_ptr cinfo,
@@ -104,23 +105,23 @@ ycc_rgb565D_convert_internal (j_decompre
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->output_width;
   /* copy these pointers into registers if possible */
   register JSAMPLE * range_limit = cinfo->sample_range_limit;
   register int * Crrtab = cconvert->Cr_r_tab;
   register int * Cbbtab = cconvert->Cb_b_tab;
-  register INT32 * Crgtab = cconvert->Cr_g_tab;
-  register INT32 * Cbgtab = cconvert->Cb_g_tab;
-  INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
+  register JLONG * Crgtab = cconvert->Cr_g_tab;
+  register JLONG * Cbgtab = cconvert->Cb_g_tab;
+  JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
   SHIFT_TEMPS
 
   while (--num_rows >= 0) {
-    INT32 rgb;
+    JLONG rgb;
     unsigned int r, g, b;
 
     inptr0 = input_buf[0][input_row];
     inptr1 = input_buf[1][input_row];
     inptr2 = input_buf[2][input_row];
     input_row++;
     outptr = *output_buf++;
     if (PACK_NEED_ALIGNMENT(outptr)) {
@@ -128,17 +129,17 @@ ycc_rgb565D_convert_internal (j_decompre
       cb = GETJSAMPLE(*inptr1++);
       cr = GETJSAMPLE(*inptr2++);
       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
       g = range_limit[DITHER_565_G(y +
                                    ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
                                                      SCALEBITS)), d0)];
       b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
       rgb = PACK_SHORT_565(r, g, b);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
       outptr += 2;
       num_cols--;
     }
     for (col = 0; col < (num_cols >> 1); col++) {
       y  = GETJSAMPLE(*inptr0++);
       cb = GETJSAMPLE(*inptr1++);
       cr = GETJSAMPLE(*inptr2++);
       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
@@ -168,17 +169,17 @@ ycc_rgb565D_convert_internal (j_decompre
       cb = GETJSAMPLE(*inptr1);
       cr = GETJSAMPLE(*inptr2);
       r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
       g = range_limit[DITHER_565_G(y +
                                    ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
                                                      SCALEBITS)), d0)];
       b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
       rgb = PACK_SHORT_565(r, g, b);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
     }
   }
 }
 
 
 INLINE
 LOCAL(void)
 rgb_rgb565_convert_internal (j_decompress_ptr cinfo,
@@ -187,30 +188,30 @@ rgb_rgb565_convert_internal (j_decompres
 {
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->output_width;
   SHIFT_TEMPS
 
   while (--num_rows >= 0) {
-    INT32 rgb;
+    JLONG rgb;
     unsigned int r, g, b;
 
     inptr0 = input_buf[0][input_row];
     inptr1 = input_buf[1][input_row];
     inptr2 = input_buf[2][input_row];
     input_row++;
     outptr = *output_buf++;
     if (PACK_NEED_ALIGNMENT(outptr)) {
       r = GETJSAMPLE(*inptr0++);
       g = GETJSAMPLE(*inptr1++);
       b = GETJSAMPLE(*inptr2++);
       rgb = PACK_SHORT_565(r, g, b);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
       outptr += 2;
       num_cols--;
     }
     for (col = 0; col < (num_cols >> 1); col++) {
       r = GETJSAMPLE(*inptr0++);
       g = GETJSAMPLE(*inptr1++);
       b = GETJSAMPLE(*inptr2++);
       rgb = PACK_SHORT_565(r, g, b);
@@ -223,51 +224,51 @@ rgb_rgb565_convert_internal (j_decompres
       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
       outptr += 4;
     }
     if (num_cols & 1) {
       r = GETJSAMPLE(*inptr0);
       g = GETJSAMPLE(*inptr1);
       b = GETJSAMPLE(*inptr2);
       rgb = PACK_SHORT_565(r, g, b);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
     }
   }
 }
 
 
 INLINE
 LOCAL(void)
 rgb_rgb565D_convert_internal (j_decompress_ptr cinfo,
                               JSAMPIMAGE input_buf, JDIMENSION input_row,
                               JSAMPARRAY output_buf, int num_rows)
 {
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2;
   register JDIMENSION col;
   register JSAMPLE * range_limit = cinfo->sample_range_limit;
   JDIMENSION num_cols = cinfo->output_width;
-  INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
+  JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
   SHIFT_TEMPS
 
   while (--num_rows >= 0) {
-    INT32 rgb;
+    JLONG rgb;
     unsigned int r, g, b;
 
     inptr0 = input_buf[0][input_row];
     inptr1 = input_buf[1][input_row];
     inptr2 = input_buf[2][input_row];
     input_row++;
     outptr = *output_buf++;
     if (PACK_NEED_ALIGNMENT(outptr)) {
       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
       rgb = PACK_SHORT_565(r, g, b);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
       outptr += 2;
       num_cols--;
     }
     for (col = 0; col < (num_cols >> 1); col++) {
       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
       d0 = DITHER_ROTATE(d0);
@@ -282,85 +283,85 @@ rgb_rgb565D_convert_internal (j_decompre
       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
       outptr += 4;
     }
     if (num_cols & 1) {
       r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0), d0)];
       g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1), d0)];
       b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2), d0)];
       rgb = PACK_SHORT_565(r, g, b);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
     }
   }
 }
 
 
 INLINE
 LOCAL(void)
 gray_rgb565_convert_internal (j_decompress_ptr cinfo,
                               JSAMPIMAGE input_buf, JDIMENSION input_row,
                               JSAMPARRAY output_buf, int num_rows)
 {
   register JSAMPROW inptr, outptr;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->output_width;
 
   while (--num_rows >= 0) {
-    INT32 rgb;
+    JLONG rgb;
     unsigned int g;
 
     inptr = input_buf[0][input_row++];
     outptr = *output_buf++;
     if (PACK_NEED_ALIGNMENT(outptr)) {
       g = *inptr++;
       rgb = PACK_SHORT_565(g, g, g);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
       outptr += 2;
       num_cols--;
     }
     for (col = 0; col < (num_cols >> 1); col++) {
       g = *inptr++;
       rgb = PACK_SHORT_565(g, g, g);
       g = *inptr++;
       rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g));
       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
       outptr += 4;
     }
     if (num_cols & 1) {
       g = *inptr;
       rgb = PACK_SHORT_565(g, g, g);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
     }
   }
 }
 
 
 INLINE
 LOCAL(void)
 gray_rgb565D_convert_internal (j_decompress_ptr cinfo,
                                JSAMPIMAGE input_buf, JDIMENSION input_row,
                                JSAMPARRAY output_buf, int num_rows)
 {
   register JSAMPROW inptr, outptr;
   register JDIMENSION col;
   register JSAMPLE * range_limit = cinfo->sample_range_limit;
   JDIMENSION num_cols = cinfo->output_width;
-  INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
+  JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
 
   while (--num_rows >= 0) {
-    INT32 rgb;
+    JLONG rgb;
     unsigned int g;
 
     inptr = input_buf[0][input_row++];
     outptr = *output_buf++;
     if (PACK_NEED_ALIGNMENT(outptr)) {
       g = *inptr++;
       g = range_limit[DITHER_565_R(g, d0)];
       rgb = PACK_SHORT_565(g, g, g);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
       outptr += 2;
       num_cols--;
     }
     for (col = 0; col < (num_cols >> 1); col++) {
       g = *inptr++;
       g = range_limit[DITHER_565_R(g, d0)];
       rgb = PACK_SHORT_565(g, g, g);
       d0 = DITHER_ROTATE(d0);
@@ -372,12 +373,12 @@ gray_rgb565D_convert_internal (j_decompr
 
       WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
       outptr += 4;
     }
     if (num_cols & 1) {
       g = *inptr;
       g = range_limit[DITHER_565_R(g, d0)];
       rgb = PACK_SHORT_565(g, g, g);
-      *(INT16*)outptr = rgb;
+      *(INT16*)outptr = (INT16)rgb;
     }
   }
 }
--- a/media/libjpeg/jdcolext.c
+++ b/media/libjpeg/jdcolext.c
@@ -1,16 +1,17 @@
 /*
  * jdcolext.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2009, 2011, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2009, 2011, 2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains output colorspace conversion routines.
  */
 
 
 /* This file is included by jdcolor.c */
 
 
@@ -36,18 +37,18 @@ ycc_rgb_convert_internal (j_decompress_p
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->output_width;
   /* copy these pointers into registers if possible */
   register JSAMPLE * range_limit = cinfo->sample_range_limit;
   register int * Crrtab = cconvert->Cr_r_tab;
   register int * Cbbtab = cconvert->Cb_b_tab;
-  register INT32 * Crgtab = cconvert->Cr_g_tab;
-  register INT32 * Cbgtab = cconvert->Cb_g_tab;
+  register JLONG * Crgtab = cconvert->Cr_g_tab;
+  register JLONG * Cbgtab = cconvert->Cb_g_tab;
   SHIFT_TEMPS
 
   while (--num_rows >= 0) {
     inptr0 = input_buf[0][input_row];
     inptr1 = input_buf[1][input_row];
     inptr2 = input_buf[2][input_row];
     input_row++;
     outptr = *output_buf++;
--- a/media/libjpeg/jdcolor.c
+++ b/media/libjpeg/jdcolor.c
@@ -3,17 +3,18 @@
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * Modified 2011 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
  * Copyright (C) 2009, 2011-2012, 2014-2015, D. R. Commander.
  * Copyright (C) 2013, Linaro Limited.
- * For conditions of distribution and use, see the accompanying README file.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains output colorspace conversion routines.
  */
 
 #define JPEG_INTERNALS
 #include "jinclude.h"
 #include "jpeglib.h"
 #include "jsimd.h"
@@ -21,26 +22,26 @@
 
 
 /* Private subobject */
 
 typedef struct {
   struct jpeg_color_deconverter pub; /* public fields */
 
   /* Private state for YCC->RGB conversion */
-  int * Cr_r_tab;               /* => table for Cr to R conversion */
-  int * Cb_b_tab;               /* => table for Cb to B conversion */
-  INT32 * Cr_g_tab;             /* => table for Cr to G conversion */
-  INT32 * Cb_g_tab;             /* => table for Cb to G conversion */
+  int *Cr_r_tab;                /* => table for Cr to R conversion */
+  int *Cb_b_tab;                /* => table for Cb to B conversion */
+  JLONG *Cr_g_tab;              /* => table for Cr to G conversion */
+  JLONG *Cb_g_tab;              /* => table for Cb to G conversion */
 
   /* Private state for RGB->Y conversion */
-  INT32 * rgb_y_tab;            /* => table for RGB to Y conversion */
+  JLONG *rgb_y_tab;             /* => table for RGB to Y conversion */
 } my_color_deconverter;
 
-typedef my_color_deconverter * my_cconvert_ptr;
+typedef my_color_deconverter *my_cconvert_ptr;
 
 
 /**************** YCbCr -> RGB conversion: most common case **************/
 /****************   RGB -> Y   conversion: less common case **************/
 
 /*
  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
@@ -68,18 +69,18 @@ typedef my_color_deconverter * my_cconve
  * 16-bit samples, but if you want lossless storage you shouldn't be changing
  * colorspace anyway.
  * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
  * values for the G calculation are left scaled up, since we must add them
  * together before rounding.
  */
 
 #define SCALEBITS       16      /* speediest right-shift on some machines */
-#define ONE_HALF        ((INT32) 1 << (SCALEBITS-1))
-#define FIX(x)          ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+#define ONE_HALF        ((JLONG) 1 << (SCALEBITS-1))
+#define FIX(x)          ((JLONG) ((x) * (1L<<SCALEBITS) + 0.5))
 
 /* We allocate one big table for RGB->Y conversion and divide it up into
  * three parts, instead of doing three alloc_small requests.  This lets us
  * use a single table base address, which can be held in a register in the
  * inner loops on many machines (more than can hold all three addresses,
  * anyway).
  */
 
@@ -206,31 +207,31 @@ typedef my_color_deconverter * my_cconve
  * Initialize tables for YCC->RGB colorspace conversion.
  */
 
 LOCAL(void)
 build_ycc_rgb_table (j_decompress_ptr cinfo)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
   int i;
-  INT32 x;
+  JLONG x;
   SHIFT_TEMPS
 
   cconvert->Cr_r_tab = (int *)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
                                 (MAXJSAMPLE+1) * sizeof(int));
   cconvert->Cb_b_tab = (int *)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
                                 (MAXJSAMPLE+1) * sizeof(int));
-  cconvert->Cr_g_tab = (INT32 *)
+  cconvert->Cr_g_tab = (JLONG *)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
-                                (MAXJSAMPLE+1) * sizeof(INT32));
-  cconvert->Cb_g_tab = (INT32 *)
+                                (MAXJSAMPLE+1) * sizeof(JLONG));
+  cconvert->Cb_g_tab = (JLONG *)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
-                                (MAXJSAMPLE+1) * sizeof(INT32));
+                                (MAXJSAMPLE+1) * sizeof(JLONG));
 
   for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
     /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
     /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
     /* Cr=>R value is nearest int to 1.40200 * x */
     cconvert->Cr_r_tab[i] = (int)
                     RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
     /* Cb=>B value is nearest int to 1.77200 * x */
@@ -297,23 +298,23 @@ ycc_rgb_convert (j_decompress_ptr cinfo,
 /*
  * Initialize for RGB->grayscale colorspace conversion.
  */
 
 LOCAL(void)
 build_rgb_y_table (j_decompress_ptr cinfo)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
-  INT32 * rgb_y_tab;
-  INT32 i;
+  JLONG *rgb_y_tab;
+  JLONG i;
 
   /* Allocate and fill in the conversion tables. */
-  cconvert->rgb_y_tab = rgb_y_tab = (INT32 *)
+  cconvert->rgb_y_tab = rgb_y_tab = (JLONG *)
     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
-                                (TABLE_SIZE * sizeof(INT32)));
+                                (TABLE_SIZE * sizeof(JLONG)));
 
   for (i = 0; i <= MAXJSAMPLE; i++) {
     rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i;
     rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i;
     rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
   }
 }
 
@@ -324,17 +325,17 @@ build_rgb_y_table (j_decompress_ptr cinf
 
 METHODDEF(void)
 rgb_gray_convert (j_decompress_ptr cinfo,
                   JSAMPIMAGE input_buf, JDIMENSION input_row,
                   JSAMPARRAY output_buf, int num_rows)
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
   register int r, g, b;
-  register INT32 * ctab = cconvert->rgb_y_tab;
+  register JLONG *ctab = cconvert->rgb_y_tab;
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->output_width;
 
   while (--num_rows >= 0) {
     inptr0 = input_buf[0][input_row];
     inptr1 = input_buf[1][input_row];
@@ -537,21 +538,21 @@ ycck_cmyk_convert (j_decompress_ptr cinf
 {
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
   register int y, cb, cr;
   register JSAMPROW outptr;
   register JSAMPROW inptr0, inptr1, inptr2, inptr3;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->output_width;
   /* copy these pointers into registers if possible */
-  register JSAMPLE * range_limit = cinfo->sample_range_limit;
-  register int * Crrtab = cconvert->Cr_r_tab;
-  register int * Cbbtab = cconvert->Cb_b_tab;
-  register INT32 * Crgtab = cconvert->Cr_g_tab;
-  register INT32 * Cbgtab = cconvert->Cb_g_tab;
+  register JSAMPLE *range_limit = cinfo->sample_range_limit;
+  register int *Crrtab = cconvert->Cr_r_tab;
+  register int *Cbbtab = cconvert->Cb_b_tab;
+  register JLONG *Crgtab = cconvert->Cr_g_tab;
+  register JLONG *Cbgtab = cconvert->Cb_g_tab;
   SHIFT_TEMPS
 
   while (--num_rows >= 0) {
     inptr0 = input_buf[0][input_row];
     inptr1 = input_buf[1][input_row];
     inptr2 = input_buf[2][input_row];
     inptr3 = input_buf[3][input_row];
     input_row++;
@@ -598,18 +599,18 @@ ycck_cmyk_convert (j_decompress_ptr cinf
 
 /* Declarations for ordered dithering
  *
  * We use a 4x4 ordered dither array packed into 32 bits.  This array is
  * sufficent for dithering RGB888 to RGB565.
  */
 
 #define DITHER_MASK       0x3
-#define DITHER_ROTATE(x)  (((x) << 24) | (((x) >> 8) & 0x00FFFFFF))
-static const INT32 dither_matrix[4] = {
+#define DITHER_ROTATE(x)  ((((x) & 0xFF) << 24) | (((x) >> 8) & 0x00FFFFFF))
+static const JLONG dither_matrix[4] = {
   0x0008020A,
   0x0C040E06,
   0x030B0109,
   0x0F070D05
 };
 
 
 static INLINE boolean is_big_endian(void)
--- a/media/libjpeg/jdct.h
+++ b/media/libjpeg/jdct.h
@@ -1,29 +1,30 @@
 /*
  * jdct.h
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1996, Thomas G. Lane.
- * It was modified by The libjpeg-turbo Project to include only code relevant
- * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * libjpeg-turbo Modifications:
+ * Copyright (C) 2015, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This include file contains common declarations for the forward and
  * inverse DCT modules.  These declarations are private to the DCT managers
  * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
  * The individual DCT algorithms are kept in separate files to ease
  * machine-dependent tuning (e.g., assembly coding).
  */
 
 
 /*
  * A forward DCT routine is given a pointer to a work area of type DCTELEM[];
  * the DCT is to be performed in-place in that buffer.  Type DCTELEM is int
- * for 8-bit samples, INT32 for 12-bit samples.  (NOTE: Floating-point DCT
+ * for 8-bit samples, JLONG for 12-bit samples.  (NOTE: Floating-point DCT
  * implementations use an array of type FAST_FLOAT, instead.)
  * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
  * The DCT outputs are returned scaled up by a factor of 8; they therefore
  * have a range of +-8K for 8-bit data, +-128K for 12-bit data.  This
  * convention improves accuracy in integer implementations and saves some
  * work in floating-point ones.
  * Quantization of the output coefficients is done by jcdctmgr.c. This
  * step requires an unsigned type and also one with twice the bits.
@@ -35,17 +36,17 @@ typedef int DCTELEM;            /* 16 or
 typedef unsigned int UDCTELEM;
 typedef unsigned long long UDCTELEM2;
 #else
 typedef short DCTELEM;  /* prefer 16 bit with SIMD for parellelism */
 typedef unsigned short UDCTELEM;
 typedef unsigned int UDCTELEM2;
 #endif
 #else
-typedef INT32 DCTELEM;          /* must have 32 bits */
+typedef JLONG DCTELEM;          /* must have 32 bits */
 typedef unsigned long long UDCTELEM2;
 #endif
 
 
 /*
  * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
  * to an output sample array.  The routine must dequantize the input data as
  * well as perform the IDCT; for dequantization, it uses the multiplier table
@@ -62,17 +63,17 @@ typedef unsigned long long UDCTELEM2;
  * Each IDCT routine has its own ideas about the best dct_table element type.
  */
 
 typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
 #if BITS_IN_JSAMPLE == 8
 typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
 #define IFAST_SCALE_BITS  2     /* fractional bits in scale factors */
 #else
-typedef INT32 IFAST_MULT_TYPE;  /* need 32 bits for scaled quantizers */
+typedef JLONG IFAST_MULT_TYPE;  /* need 32 bits for scaled quantizers */
 #define IFAST_SCALE_BITS  13    /* fractional bits in scale factors */
 #endif
 typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
 
 
 /*
  * Each IDCT routine is responsible for range-limiting its results and
  * converting them to unsigned form (0..MAXJSAMPLE).  The raw outputs could
@@ -84,117 +85,117 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* p
 
 #define IDCT_range_limit(cinfo)  ((cinfo)->sample_range_limit + CENTERJSAMPLE)
 
 #define RANGE_MASK  (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
 
 
 /* Extern declarations for the forward and inverse DCT routines. */
 
-EXTERN(void) jpeg_fdct_islow (DCTELEM * data);
-EXTERN(void) jpeg_fdct_ifast (DCTELEM * data);
-EXTERN(void) jpeg_fdct_float (FAST_FLOAT * data);
+EXTERN(void) jpeg_fdct_islow (DCTELEM *data);
+EXTERN(void) jpeg_fdct_ifast (DCTELEM *data);
+EXTERN(void) jpeg_fdct_float (FAST_FLOAT *data);
 
 EXTERN(void) jpeg_idct_islow
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_ifast
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_float
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_7x7
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_6x6
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_5x5
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_4x4
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_3x3
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_2x2
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_1x1
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_9x9
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_10x10
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_11x11
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_12x12
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_13x13
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_14x14
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_15x15
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 EXTERN(void) jpeg_idct_16x16
-        (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        (j_decompress_ptr cinfo, jpeg_component_info *compptr,
          JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
 
 
 /*
  * Macros for handling fixed-point arithmetic; these are used by many
  * but not all of the DCT/IDCT modules.
  *
- * All values are expected to be of type INT32.
+ * All values are expected to be of type JLONG.
  * Fractional constants are scaled left by CONST_BITS bits.
  * CONST_BITS is defined within each module using these macros,
  * and may differ from one module to the next.
  */
 
-#define ONE     ((INT32) 1)
+#define ONE     ((JLONG) 1)
 #define CONST_SCALE (ONE << CONST_BITS)
 
 /* Convert a positive real constant to an integer scaled by CONST_SCALE.
  * Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
  * thus causing a lot of useless floating-point operations at run time.
  */
 
-#define FIX(x)  ((INT32) ((x) * CONST_SCALE + 0.5))
+#define FIX(x)  ((JLONG) ((x) * CONST_SCALE + 0.5))
 
-/* Descale and correctly round an INT32 value that's scaled by N bits.
+/* Descale and correctly round a JLONG value that's scaled by N bits.
  * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
  * the fudge factor is correct for either sign of X.
  */
 
 #define DESCALE(x,n)  RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
 
-/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+/* Multiply a JLONG variable by a JLONG constant to yield a JLONG result.
  * This macro is used only when the two inputs will actually be no more than
  * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
  * full 32x32 multiply.  This provides a useful speedup on many machines.
  * Unfortunately there is no way to specify a 16x16->32 multiply portably
  * in C, but some C compilers will do the right thing if you provide the
  * correct combination of casts.
  */
 
 #ifdef SHORTxSHORT_32           /* may work if 'int' is 32 bits */
 #define MULTIPLY16C16(var,const)  (((INT16) (var)) * ((INT16) (const)))
 #endif
 #ifdef SHORTxLCONST_32          /* known to work with Microsoft C 6.0 */
-#define MULTIPLY16C16(var,const)  (((INT16) (var)) * ((INT32) (const)))
+#define MULTIPLY16C16(var,const)  (((INT16) (var)) * ((JLONG) (const)))
 #endif
 
 #ifndef MULTIPLY16C16           /* default definition */
 #define MULTIPLY16C16(var,const)  ((var) * (const))
 #endif
 
 /* Same except both inputs are variables. */
 
--- a/media/libjpeg/jddctmgr.c
+++ b/media/libjpeg/jddctmgr.c
@@ -1,19 +1,20 @@
 /*
  * jddctmgr.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1996, Thomas G. Lane.
  * Modified 2002-2010 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright (C) 2010, D. R. Commander.
- * Copyright (C) 2013, MIPS Technologies, Inc., California
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2010, 2015, D. R. Commander.
+ * Copyright (C) 2013, MIPS Technologies, Inc., California.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains the inverse-DCT management logic.
  * This code selects a particular IDCT implementation to be used,
  * and it performs related housekeeping chores.  No code in this file
  * is executed per IDCT step, only during output pass setup.
  *
  * Note that the IDCT routines are responsible for performing coefficient
  * dequantization as well as the IDCT proper.  This module sets up the
@@ -53,17 +54,17 @@ typedef struct {
   /* This array contains the IDCT method code that each multiplier table
    * is currently set up for, or -1 if it's not yet set up.
    * The actual multiplier tables are pointed to by dct_table in the
    * per-component comp_info structures.
    */
   int cur_method[MAX_COMPONENTS];
 } my_idct_controller;
 
-typedef my_idct_controller * my_idct_ptr;
+typedef my_idct_controller *my_idct_ptr;
 
 
 /* Allocated multiplier tables: big enough for any supported variant */
 
 typedef union {
   ISLOW_MULT_TYPE islow_array[DCTSIZE2];
 #ifdef DCT_IFAST_SUPPORTED
   IFAST_MULT_TYPE ifast_array[DCTSIZE2];
@@ -95,17 +96,17 @@ typedef union {
 METHODDEF(void)
 start_pass (j_decompress_ptr cinfo)
 {
   my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
   int ci, i;
   jpeg_component_info *compptr;
   int method = 0;
   inverse_DCT_method_ptr method_ptr = NULL;
-  JQUANT_TBL * qtbl;
+  JQUANT_TBL *qtbl;
 
   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
        ci++, compptr++) {
     /* Select the proper IDCT routine for this component's scaling */
     switch (compptr->_DCT_scaled_size) {
 #ifdef IDCT_SCALING_SUPPORTED
     case 1:
       method_ptr = jpeg_idct_1x1;
@@ -240,66 +241,66 @@ start_pass (j_decompress_ptr cinfo)
     idct->cur_method[ci] = method;
     switch (method) {
 #ifdef PROVIDE_ISLOW_TABLES
     case JDCT_ISLOW:
       {
         /* For LL&M IDCT method, multipliers are equal to raw quantization
          * coefficients, but are stored as ints to ensure access efficiency.
          */
-        ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
+        ISLOW_MULT_TYPE *ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
         for (i = 0; i < DCTSIZE2; i++) {
           ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
         }
       }
       break;
 #endif
 #ifdef DCT_IFAST_SUPPORTED
     case JDCT_IFAST:
       {
         /* For AA&N IDCT method, multipliers are equal to quantization
          * coefficients scaled by scalefactor[row]*scalefactor[col], where
          *   scalefactor[0] = 1
          *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7
          * For integer operation, the multiplier table is to be scaled by
          * IFAST_SCALE_BITS.
          */
-        IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
+        IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
 #define CONST_BITS 14
         static const INT16 aanscales[DCTSIZE2] = {
           /* precomputed values scaled up by 14 bits */
           16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
           22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270,
           21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906,
           19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315,
           16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
           12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552,
            8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446,
            4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247
         };
         SHIFT_TEMPS
 
         for (i = 0; i < DCTSIZE2; i++) {
           ifmtbl[i] = (IFAST_MULT_TYPE)
-            DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
-                                  (INT32) aanscales[i]),
+            DESCALE(MULTIPLY16V16((JLONG) qtbl->quantval[i],
+                                  (JLONG) aanscales[i]),
                     CONST_BITS-IFAST_SCALE_BITS);
         }
       }
       break;
 #endif
 #ifdef DCT_FLOAT_SUPPORTED
     case JDCT_FLOAT:
       {
         /* For float AA&N IDCT method, multipliers are equal to quantization
          * coefficients scaled by scalefactor[row]*scalefactor[col], where
          *   scalefactor[0] = 1
          *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7
          */
-        FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
+        FLOAT_MULT_TYPE *fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
         int row, col;
         static const double aanscalefactor[DCTSIZE] = {
           1.0, 1.387039845, 1.306562965, 1.175875602,
           1.0, 0.785694958, 0.541196100, 0.275899379
         };
 
         i = 0;
         for (row = 0; row < DCTSIZE; row++) {
--- a/media/libjpeg/jdhuff.c
+++ b/media/libjpeg/jdhuff.c
@@ -1,16 +1,17 @@
 /*
  * jdhuff.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2009-2011, 2016, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains Huffman entropy decoding routines.
  *
  * Much of the complexity here has to do with supporting input suspension.
  * If the data source module demands suspension, we want to be able to back
  * up to the start of the current MCU.  To do this, we copy state variables
  * into local working storage, and update them back to the permanent
  * storage only upon successful completion of an MCU.
@@ -61,43 +62,43 @@ typedef struct {
    */
   bitread_perm_state bitstate;  /* Bit buffer at start of MCU */
   savable_state saved;          /* Other state at start of MCU */
 
   /* These fields are NOT loaded into local working state. */
   unsigned int restarts_to_go;  /* MCUs left in this restart interval */
 
   /* Pointers to derived tables (these workspaces have image lifespan) */
-  d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
-  d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+  d_derived_tbl *dc_derived_tbls[NUM_HUFF_TBLS];
+  d_derived_tbl *ac_derived_tbls[NUM_HUFF_TBLS];
 
   /* Precalculated info set up by start_pass for use in decode_mcu: */
 
   /* Pointers to derived tables to be used for each block within an MCU */
-  d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU];
-  d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU];
+  d_derived_tbl *dc_cur_tbls[D_MAX_BLOCKS_IN_MCU];
+  d_derived_tbl *ac_cur_tbls[D_MAX_BLOCKS_IN_MCU];
   /* Whether we care about the DC and AC coefficient values for each block */
   boolean dc_needed[D_MAX_BLOCKS_IN_MCU];
   boolean ac_needed[D_MAX_BLOCKS_IN_MCU];
 } huff_entropy_decoder;
 
-typedef huff_entropy_decoder * huff_entropy_ptr;
+typedef huff_entropy_decoder *huff_entropy_ptr;
 
 
 /*
  * Initialize for a Huffman-compressed scan.
  */
 
 METHODDEF(void)
 start_pass_huff_decoder (j_decompress_ptr cinfo)
 {
   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
   int ci, blkn, dctbl, actbl;
   d_derived_tbl **pdtbl;
-  jpeg_component_info * compptr;
+  jpeg_component_info *compptr;
 
   /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
    * This ought to be an error condition, but we make it a warning because
    * there are some baseline files out there with all zeroes in these bytes.
    */
   if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
       cinfo->Ah != 0 || cinfo->Al != 0)
     WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
@@ -147,17 +148,17 @@ start_pass_huff_decoder (j_decompress_pt
  * Compute the derived values for a Huffman table.
  * This routine also performs some validation checks on the table.
  *
  * Note this is also used by jdphuff.c.
  */
 
 GLOBAL(void)
 jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
-                         d_derived_tbl ** pdtbl)
+                         d_derived_tbl **pdtbl)
 {
   JHUFF_TBL *htbl;
   d_derived_tbl *dtbl;
   int p, i, l, si, numsymbols;
   int lookbits, ctr;
   char huffsize[257];
   unsigned int huffcode[257];
   unsigned int code;
@@ -204,31 +205,31 @@ jpeg_make_d_derived_tbl (j_decompress_pt
   while (huffsize[p]) {
     while (((int) huffsize[p]) == si) {
       huffcode[p++] = code;
       code++;
     }
     /* code is now 1 more than the last code used for codelength si; but
      * it must still fit in si bits, since no code is allowed to be all ones.
      */
-    if (((INT32) code) >= (((INT32) 1) << si))
+    if (((JLONG) code) >= (((JLONG) 1) << si))
       ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
     code <<= 1;
     si++;
   }
 
   /* Figure F.15: generate decoding tables for bit-sequential decoding */
 
   p = 0;
   for (l = 1; l <= 16; l++) {
     if (htbl->bits[l]) {
       /* valoffset[l] = huffval[] index of 1st symbol of code length l,
        * minus the minimum code of length l
        */
-      dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p];
+      dtbl->valoffset[l] = (JLONG) p - (JLONG) huffcode[p];
       p += htbl->bits[l];
       dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
     } else {
       dtbl->maxcode[l] = -1;    /* -1 if no codes of this length */
     }
   }
   dtbl->valoffset[17] = 0;
   dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */
@@ -290,23 +291,23 @@ jpeg_make_d_derived_tbl (j_decompress_pt
 #ifdef SLOW_SHIFT_32
 #define MIN_GET_BITS  15        /* minimum allowable value */
 #else
 #define MIN_GET_BITS  (BIT_BUF_SIZE-7)
 #endif
 
 
 GLOBAL(boolean)
-jpeg_fill_bit_buffer (bitread_working_state * state,
+jpeg_fill_bit_buffer (bitread_working_state *state,
                       register bit_buf_type get_buffer, register int bits_left,
                       int nbits)
 /* Load up the bit buffer to a depth of at least nbits */
 {
   /* Copy heavily used state fields into locals (hopefully registers) */
-  register const JOCTET * next_input_byte = state->next_input_byte;
+  register const JOCTET *next_input_byte = state->next_input_byte;
   register size_t bytes_in_buffer = state->bytes_in_buffer;
   j_decompress_ptr cinfo = state->cinfo;
 
   /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
   /* (It is assumed that no request will be for more than that many bits.) */
   /* We fail to do so only if we hit a marker or are forced to suspend. */
 
   if (cinfo->unread_marker == 0) {      /* cannot advance past a marker */
@@ -440,22 +441,22 @@ jpeg_fill_bit_buffer (bitread_working_st
 
 
 /*
  * Out-of-line code for Huffman code decoding.
  * See jdhuff.h for info about usage.
  */
 
 GLOBAL(int)
-jpeg_huff_decode (bitread_working_state * state,
+jpeg_huff_decode (bitread_working_state *state,
                   register bit_buf_type get_buffer, register int bits_left,
-                  d_derived_tbl * htbl, int min_bits)
+                  d_derived_tbl *htbl, int min_bits)
 {
   register int l = min_bits;
-  register INT32 code;
+  register JLONG code;
 
   /* HUFF_DECODE has determined that the code is at least min_bits */
   /* bits long, so fetch that many bits in one swoop. */
 
   CHECK_BIT_BUFFER(*state, l, return -1);
   code = GET_BITS(l);
 
   /* Collect the rest of the Huffman code one bit at a time. */
@@ -559,19 +560,19 @@ decode_mcu_slow (j_decompress_ptr cinfo,
   savable_state state;
   /* Outer loop handles each block in the MCU */
 
   /* Load up working state */
   BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
   ASSIGN_STATE(state, entropy->saved);
 
   for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
-    JBLOCKROW block = MCU_data[blkn];
-    d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
-    d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
+    JBLOCKROW block = MCU_data ? MCU_data[blkn] : NULL;
+    d_derived_tbl *dctbl = entropy->dc_cur_tbls[blkn];
+    d_derived_tbl *actbl = entropy->ac_cur_tbls[blkn];
     register int s, k, r;
 
     /* Decode a single block's worth of coefficients */
 
     /* Section F.2.2.1: decode the DC coefficient difference */
     HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
     if (s) {
       CHECK_BIT_BUFFER(br_state, s, return FALSE);
@@ -579,21 +580,23 @@ decode_mcu_slow (j_decompress_ptr cinfo,
       s = HUFF_EXTEND(r, s);
     }
 
     if (entropy->dc_needed[blkn]) {
       /* Convert DC difference to actual value, update last_dc_val */
       int ci = cinfo->MCU_membership[blkn];
       s += state.last_dc_val[ci];
       state.last_dc_val[ci] = s;
-      /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
-      (*block)[0] = (JCOEF) s;
+      if (block) {
+        /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
+        (*block)[0] = (JCOEF) s;
+      }
     }
 
-    if (entropy->ac_needed[blkn]) {
+    if (entropy->ac_needed[blkn] && block) {
 
       /* Section F.2.2.2: decode the AC coefficients */
       /* Since zeroes are skipped, output area must be cleared beforehand */
       for (k = 1; k < DCTSIZE2; k++) {
         HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
 
         r = s >> 4;
         s &= 15;
@@ -656,36 +659,37 @@ decode_mcu_fast (j_decompress_ptr cinfo,
   /* Outer loop handles each block in the MCU */
 
   /* Load up working state */
   BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
   buffer = (JOCTET *) br_state.next_input_byte;
   ASSIGN_STATE(state, entropy->saved);
 
   for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
-    JBLOCKROW block = MCU_data[blkn];
-    d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
-    d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
+    JBLOCKROW block = MCU_data ? MCU_data[blkn] : NULL;
+    d_derived_tbl *dctbl = entropy->dc_cur_tbls[blkn];
+    d_derived_tbl *actbl = entropy->ac_cur_tbls[blkn];
     register int s, k, r, l;
 
     HUFF_DECODE_FAST(s, l, dctbl, slow_decode_mcu);
     if (s) {
       FILL_BIT_BUFFER_FAST
       r = GET_BITS(s);
       s = HUFF_EXTEND(r, s);
     }
 
     if (entropy->dc_needed[blkn]) {
       int ci = cinfo->MCU_membership[blkn];
       s += state.last_dc_val[ci];
       state.last_dc_val[ci] = s;
-      (*block)[0] = (JCOEF) s;
+      if (block)
+        (*block)[0] = (JCOEF) s;
     }
 
-    if (entropy->ac_needed[blkn]) {
+    if (entropy->ac_needed[blkn] && block) {
 
       for (k = 1; k < DCTSIZE2; k++) {
         HUFF_DECODE_FAST(s, l, actbl, slow_decode_mcu);
         r = s >> 4;
         s &= 15;
 
         if (s) {
           k += r;
@@ -742,17 +746,17 @@ slow_decode_mcu:
  * (Wholesale zeroing is usually a little faster than retail...)
  *
  * Returns FALSE if data source requested suspension.  In that case no
  * changes have been made to permanent state.  (Exception: some output
  * coefficients may already have been assigned.  This is harmless for
  * this module, since we'll just re-assign them on the next call.)
  */
 
-#define BUFSIZE (DCTSIZE2 * 2)
+#define BUFSIZE (DCTSIZE2 * 8)
 
 METHODDEF(boolean)
 decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
 {
   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
   int usefast = 1;
 
   /* Process restart marker if needed; may have to suspend */
--- a/media/libjpeg/jdhuff.h
+++ b/media/libjpeg/jdhuff.h
@@ -1,32 +1,35 @@
 /*
  * jdhuff.h
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2010-2011, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2010-2011, 2015-2016, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains declarations for Huffman entropy decoding routines
  * that are shared between the sequential decoder (jdhuff.c) and the
  * progressive decoder (jdphuff.c).  No other modules need to see these.
  */
 
+#include "jconfigint.h"
+
 
 /* Derived data constructed for each Huffman table */
 
 #define HUFF_LOOKAHEAD  8       /* # of bits of lookahead */
 
 typedef struct {
   /* Basic tables: (element [0] of each array is unused) */
-  INT32 maxcode[18];            /* largest code of length k (-1 if none) */
+  JLONG maxcode[18];            /* largest code of length k (-1 if none) */
   /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
-  INT32 valoffset[18];          /* huffval[] offset for codes of length k */
+  JLONG valoffset[18];          /* huffval[] offset for codes of length k */
   /* valoffset[k] = huffval[] index of 1st symbol of code length k, less
    * the smallest code of length k; so given a code of length k, the
    * corresponding symbol is huffval[code + valoffset[k]]
    */
 
   /* Link to public Huffman table (needed only in jpeg_huff_decode) */
   JHUFF_TBL *pub;
 
@@ -68,22 +71,22 @@ EXTERN(void) jpeg_make_d_derived_tbl
  */
 
 #if !defined(_WIN32) && !defined(SIZEOF_SIZE_T)
 #error Cannot determine word size
 #endif
 
 #if SIZEOF_SIZE_T==8 || defined(_WIN64)
 
-typedef size_t bit_buf_type;    /* type of bit-extraction buffer */
+typedef size_t bit_buf_type;            /* type of bit-extraction buffer */
 #define BIT_BUF_SIZE  64                /* size of buffer in bits */
 
 #else
 
-typedef INT32 bit_buf_type;     /* type of bit-extraction buffer */
+typedef unsigned long bit_buf_type;     /* type of bit-extraction buffer */
 #define BIT_BUF_SIZE  32                /* size of buffer in bits */
 
 #endif
 
 /* If long is > 32 bits on your machine, and shifting/masking longs is
  * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
  * appropriately should be a win.  Unfortunately we can't define the size
  * with something like  #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
@@ -93,17 +96,17 @@ typedef INT32 bit_buf_type;     /* type 
 typedef struct {                /* Bitreading state saved across MCUs */
   bit_buf_type get_buffer;      /* current bit-extraction buffer */
   int bits_left;                /* # of unused bits in it */
 } bitread_perm_state;
 
 typedef struct {                /* Bitreading working state within an MCU */
   /* Current data source location */
   /* We need a copy, rather than munging the original, in case of suspension */
-  const JOCTET * next_input_byte; /* => next byte to read from source */
+  const JOCTET *next_input_byte; /* => next byte to read from source */
   size_t bytes_in_buffer;       /* # of bytes remaining in source buffer */
   /* Bit input buffer --- note these values are kept in register variables,
    * not in this struct, inside the inner loops.
    */
   bit_buf_type get_buffer;      /* current bit-extraction buffer */
   int bits_left;                /* # of unused bits in it */
   /* Pointer needed by jpeg_fill_bit_buffer. */
   j_decompress_ptr cinfo;       /* back link to decompress master record */
@@ -158,17 +161,17 @@ typedef struct {                /* Bitre
 #define PEEK_BITS(nbits) \
         (((int) (get_buffer >> (bits_left -  (nbits)))) & ((1<<(nbits))-1))
 
 #define DROP_BITS(nbits) \
         (bits_left -= (nbits))
 
 /* Load up the bit buffer to a depth of at least nbits */
 EXTERN(boolean) jpeg_fill_bit_buffer
-        (bitread_working_state * state, register bit_buf_type get_buffer,
+        (bitread_working_state *state, register bit_buf_type get_buffer,
          register int bits_left, int nbits);
 
 
 /*
  * Code for extracting next Huffman-coded symbol from input bit stream.
  * Again, this is time-critical and we make the main paths be macros.
  *
  * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
@@ -224,10 +227,10 @@ slowlabel: \
     } \
     if (nb > 16) \
       goto slowlabel; \
     s = htbl->pub->huffval[ (int) (s + htbl->valoffset[nb]) ]; \
   }
 
 /* Out-of-line case for Huffman code fetching */
 EXTERN(int) jpeg_huff_decode
-        (bitread_working_state * state, register bit_buf_type get_buffer,
-         register int bits_left, d_derived_tbl * htbl, int min_bits);
+        (bitread_working_state *state, register bit_buf_type get_buffer,
+         register int bits_left, d_derived_tbl *htbl, int min_bits);
--- a/media/libjpeg/jdinput.c
+++ b/media/libjpeg/jdinput.c
@@ -1,16 +1,18 @@
 /*
  * jdinput.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2010, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2010, 2016, D. R. Commander.
+ * Copyright (C) 2015, Google, Inc.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains input control logic for the JPEG decompressor.
  * These routines are concerned with controlling the decompressor's input
  * processing (marker reading and coefficient decoding).  The actual input
  * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
  */
 
 #define JPEG_INTERNALS
@@ -22,17 +24,17 @@
 /* Private state */
 
 typedef struct {
   struct jpeg_input_controller pub; /* public fields */
 
   boolean inheaders;            /* TRUE until first SOS is reached */
 } my_input_controller;
 
-typedef my_input_controller * my_inputctl_ptr;
+typedef my_input_controller *my_inputctl_ptr;
 
 
 /* Forward declarations */
 METHODDEF(int) consume_markers (j_decompress_ptr cinfo);
 
 
 /*
  * Routines to calculate various quantities related to the size of the image.
@@ -99,16 +101,21 @@ initial_setup (j_decompress_ptr cinfo)
 #endif
     /* Size in DCT blocks */
     compptr->width_in_blocks = (JDIMENSION)
       jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
                     (long) (cinfo->max_h_samp_factor * DCTSIZE));
     compptr->height_in_blocks = (JDIMENSION)
       jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
                     (long) (cinfo->max_v_samp_factor * DCTSIZE));
+    /* Set the first and last MCU columns to decompress from multi-scan images.
+     * By default, decompress all of the MCU columns.
+     */
+    cinfo->master->first_MCU_col[ci] = 0;
+    cinfo->master->last_MCU_col[ci] = compptr->width_in_blocks - 1;
     /* downsampled_width and downsampled_height will also be overridden by
      * jdmaster.c if we are doing full decompression.  The transcoder library
      * doesn't use these values, but the calling application might.
      */
     /* Size in samples */
     compptr->downsampled_width = (JDIMENSION)
       jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
                     (long) cinfo->max_h_samp_factor);
@@ -233,17 +240,17 @@ per_scan_setup (j_decompress_ptr cinfo)
  * not at the current Q-table slots.
  */
 
 LOCAL(void)
 latch_quant_tables (j_decompress_ptr cinfo)
 {
   int ci, qtblno;
   jpeg_component_info *compptr;
-  JQUANT_TBL * qtbl;
+  JQUANT_TBL *qtbl;
 
   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
     compptr = cinfo->cur_comp_info[ci];
     /* No work if we already saved Q-table for this component */
     if (compptr->quant_table != NULL)
       continue;
     /* Make sure specified quantization table is present */
     qtblno = compptr->quant_tbl_no;
--- a/media/libjpeg/jdmainct.c
+++ b/media/libjpeg/jdmainct.c
@@ -1,29 +1,28 @@
 /*
  * jdmainct.c
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1996, Thomas G. Lane.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2010, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2010, 2016, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
  *
  * This file contains the main buffer controller for decompression.
  * The main buffer lies between the JPEG decompressor proper and the
  * post-processor; it holds downsampled data in the JPEG colorspace.
  *
  * Note that this code is bypassed in raw-data mode, since the application
  * supplies the equivalent of the main buffer in that case.
  */
 
-#define JPEG_INTERNALS
 #include "jinclude.h"
-#include "jpeglib.h"
-#include "jpegcomp.h"
+#include "jdmainct.h"
 
 
 /*
  * In the current system design, the main buffer need never be a full-image
  * buffer; any full-height buffers will be found inside the coefficient or
  * postprocessing controllers.  Nonetheless, the main controller is not
  * trivial.  Its responsibility is to provide context rows for upsampling/
  * rescaling, and doing this in an efficient fashion is a bit tricky.
@@ -107,46 +106,16 @@
  * must be different (eg, we must read two iMCU rows before we can emit the
  * first row group).  For now, we simply do not support providing context
  * rows when min_DCT_scaled_size is 1.  That combination seems unlikely to
  * be worth providing --- if someone wants a 1/8th-size preview, they probably
  * want it quick and dirty, so a context-free upsampler is sufficient.
  */
 
 
-/* Private buffer controller object */
-
-typedef struct {
-  struct jpeg_d_main_controller pub; /* public fields */
-
-  /* Pointer to allocated workspace (M or M+2 row groups). */
-  JSAMPARRAY buffer[MAX_COMPONENTS];
-
-  boolean buffer_full;          /* Have we gotten an iMCU row from decoder? */
-  JDIMENSION rowgroup_ctr;      /* counts row groups output to postprocessor */
-
-  /* Remaining fields are only used in the context case. */
-
-  /* These are the master pointers to the funny-order pointer lists. */
-  JSAMPIMAGE xbuffer[2];        /* pointers to weird pointer lists */
-
-  int whichptr;                 /* indicates which pointer set is now in use */
-  int context_state;            /* process_data state machine status */
-  JDIMENSION rowgroups_avail;   /* row groups available to postprocessor */
-  JDIMENSION iMCU_row_ctr;      /* counts iMCU rows to detect image top/bot */
-} my_main_controller;
-
-typedef my_main_controller * my_main_ptr;
-
-/* context_state values: */
-#define CTX_PREPARE_FOR_IMCU    0       /* need to prepare for MCU row */
-#define CTX_PROCESS_IMCU        1       /* feeding iMCU to postprocessor */
-#define CTX_POSTPONED_ROW       2       /* feeding postponed row group */
-
-
 /* Forward declarations */
 METHODDEF(void) process_data_simple_main
         (j_decompress_ptr cinfo, JSAMPARRAY output_buf,
          JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
 METHODDEF(void) process_data_context_main
         (j_decompress_ptr cinfo, JSAMPARRAY output_buf,
          JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
 #ifdef QUANT_2PASS_SUPPORTED
@@ -233,44 +202,16 @@ make_funny_pointers (j_decompress_ptr ci
     for (i = 0; i < rgroup; i++) {
       xbuf0[i - rgroup] = xbuf0[0];
     }
   }
 }
 
 
 LOCAL(void)
-set_wraparound_pointers (j_decompress_ptr cinfo)
-/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
- * This changes the pointer list state from top-of-image to the normal state.
- */
-{
-  my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
-  int ci, i, rgroup;
-  int M = cinfo->_min_DCT_scaled_size;
-  jpeg_component_info *compptr;
-  JSAMPARRAY xbuf0, xbuf1;
-
-  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
-       ci++, compptr++) {
-    rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) /
-      cinfo->_min_DCT_scaled_size; /* height of a row group of component */
-    xbuf0 = main_ptr->xbuffer[0][ci];
-    xbuf1 = main_ptr->xbuffer[1][ci];
-    for (i = 0; i < rgroup; i++) {
-      xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
-      xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
-      xbuf0[rgroup*(M+2) + i] = xbuf0[i];
-      xbuf1[rgroup*(M+2) + i] = xbuf1[i];
-    }
-  }
-}
-
-
-LOCAL(void)
 set_bottom_pointers (j_decompress_ptr cinfo)
 /* Change the pointer lists to duplicate the last sample row at the bottom
  * of the image.  whichptr indicates which xbuffer holds the final iMCU row.
  * Also sets rowgroups_avail to indicate number of nondummy row groups in row.
  */
 {
   my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
   int ci, i, rgroup, iMCUheight, rows_left;
new file mode 100644
--- /dev/null
+++ b/media/libjpeg/jdmainct.h
@@ -0,0 +1,71 @@
+/*
+ * jdmainct.h
+ *
+ * This file was part of the Independent JPEG Group's software:
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
+ */
+
+#define JPEG_INTERNALS
+#include "jpeglib.h"
+#include "jpegcomp.h"
+
+
+/* Private buffer controller object */
+
+typedef struct {
+  struct jpeg_d_main_controller pub; /* public fields */
+
+  /* Pointer to allocated workspace (M or M+2 row groups). */
+  JSAMPARRAY buffer[MAX_COMPONENTS];
+
+  boolean buffer_full;          /* Have we gotten an iMCU row from decoder? */
+  JDIMENSION rowgroup_ctr;      /* counts row groups output to postprocessor */
+
+  /* Remaining fields are only used in the context case. */
+
+  /* These are the master pointers to the funny-order pointer lists. */
+  JSAMPIMAGE xbuffer[2];        /* pointers to weird pointer lists */
+
+  int whichptr;                 /* indicates which pointer set is now in use */
+  int context_state;            /* process_data state machine status */
+  JDIMENSION rowgroups_avail;   /* row groups available to postprocessor */
+  JDIMENSION iMCU_row_ctr;      /* counts iMCU rows to detect image top/bot */
+} my_main_controller;
+
+typedef my_main_controller *my_main_ptr;
+
+
+/* context_state values: */
+#define CTX_PREPARE_FOR_IMCU    0       /* need to prepare for MCU row */
+#define CTX_PROCESS_IMCU        1       /* feeding iMCU to postprocessor */
+#define CTX_POSTPONED_ROW       2       /* feeding postponed row group */
+
+
+LOCAL(void)
+set_wraparound_pointers (j_decompress_ptr cinfo)
+/* Set up the "wraparound&quo