Import Cobalt 22.master.0.304062
diff --git a/src/base/files/file_path.cc b/src/base/files/file_path.cc
index 043d144..4ce94c9 100644
--- a/src/base/files/file_path.cc
+++ b/src/base/files/file_path.cc
@@ -5,11 +5,10 @@
 #include "base/files/file_path.h"
 
 #include <string.h>
+
 #include <algorithm>
-
-#include "starboard/types.h"
-
-#include "starboard/common/string.h"
+#include <set>
+#include <string>
 
 #include "base/logging.h"
 #include "base/macros.h"
@@ -19,6 +18,8 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "starboard/common/string.h"
+#include "starboard/types.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/scoped_cftyperef.h"
@@ -57,7 +58,28 @@
        (path[0] >= L'a' && path[0] <= L'z'))) {
     return 1;
   }
-#endif  // FILE_PATH_USES_DRIVE_LETTERS
+#elif defined(FILE_PATH_USES_MOUNT_POINT_NAME)
+  StringType::size_type delimiter_position = std::string(path).find(":");
+
+  auto has_disabled_symbols = [](std::string test_string) {
+    std::set<char> disabled_set = {'*', ':', '<', '>', '?', '|'};
+    std::set<char> tmp(test_string.begin(), test_string.end());
+    std::set<char> intersect;
+    std::set_intersection(disabled_set.begin(), disabled_set.end(), tmp.begin(),
+                          tmp.end(),
+                          std::inserter(intersect, intersect.begin()));
+    return !intersect.empty();
+  };
+  std::string mount_point = std::string(path).substr(0, delimiter_position);
+  std::string file_name = std::string(path).substr(delimiter_position + 1);
+  if (has_disabled_symbols(mount_point) || has_disabled_symbols(file_name)) {
+    return StringType::npos;
+  }
+
+  if (mount_point.size() >= 2 && delimiter_position != std::string::npos) {
+    return delimiter_position;
+  }
+#endif
   return StringType::npos;
 }
 
@@ -81,7 +103,8 @@
 #endif  // defined(FILE_PATH_USES_DRIVE_LETTERS)
 
 bool IsPathAbsolute(StringPieceType path) {
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
+#if defined(FILE_PATH_USES_DRIVE_LETTERS) || \
+    defined(FILE_PATH_USES_MOUNT_POINT_NAME)
   StringType::size_type letter = FindDriveLetter(path);
   if (letter != StringType::npos) {
     // Look for a separator right after the drive specification.
@@ -91,10 +114,10 @@
   // Look for a pair of leading separators.
   return path.length() > 1 &&
       FilePath::IsSeparator(path[0]) && FilePath::IsSeparator(path[1]);
-#else  // FILE_PATH_USES_DRIVE_LETTERS
+#else  // FILE_PATH_USES_DRIVE_LETTERS || FILE_PATH_USES_MOUNT_POINT_NAME
   // Look for a separator in the first position.
   return path.length() > 0 && FilePath::IsSeparator(path[0]);
-#endif  // FILE_PATH_USES_DRIVE_LETTERS
+#endif  // FILE_PATH_USES_DRIVE_LETTERS || FILE_PATH_USES_MOUNT_POINT_NAME
 }
 
 bool AreAllSeparators(const StringType& input) {
diff --git a/src/base/files/file_path_unittest.cc b/src/base/files/file_path_unittest.cc
index 593b1a0..f7c698a 100644
--- a/src/base/files/file_path_unittest.cc
+++ b/src/base/files/file_path_unittest.cc
@@ -415,12 +415,31 @@
     { FPL("c:/.."),  true },
     { FPL("C:/a"),   true },
     { FPL("d:/a"),   true },
-#else  // FILE_PATH_USES_DRIVE_LETTERS
-    { FPL("/"),      true },
-    { FPL("/a"),     true },
-    { FPL("/."),     true },
-    { FPL("/.."),    true },
-    { FPL("c:/"),    false },
+#elif defined(FILE_PATH_USES_MOUNT_POINT_NAME)
+    { FPL("/"),         false },
+    { FPL("/a"),        false },
+    { FPL("/."),        false },
+    { FPL("/.."),       false },
+    { FPL("ab:/."),     true  },
+    { FPL("ab:/"),      true  },
+    { FPL("ab:"),       false },
+    { FPL("b:"),        false },
+    { FPL("b:/"),       false },
+    { FPL("cache:/"),   true },
+    { FPL("rom:/"),     true },
+    { FPL("cache:/."),  true },
+    { FPL("rom:/."),    true },
+    { FPL("cache:/a"),  true },
+    { FPL("rom:/a"),    true },
+    { FPL("cache:/.."), true },
+    { FPL("rom:/.."),   true },
+#else  // !defined(FILE_PATH_USES_DRIVE_LETTERS) && \
+          !defined(FILE_PATH_USES_MOUNT_POINT_NAME)
+    { FPL("/"),   true },
+    { FPL("/a"),  true },
+    { FPL("/."),  true },
+    { FPL("/.."), true },
+    { FPL("c:/"), false },
 #endif  // FILE_PATH_USES_DRIVE_LETTERS
 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
     { FPL("a\\b"),   false },
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 0c55a1f..97ccdad 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-303689
\ No newline at end of file
+304062
\ No newline at end of file
diff --git a/src/cobalt/build/save_build_id.py b/src/cobalt/build/save_build_id.py
index 014e80d..fc81ab9 100755
--- a/src/cobalt/build/save_build_id.py
+++ b/src/cobalt/build/save_build_id.py
@@ -63,7 +63,12 @@
     return 0
 
   if not options.build_id:
-    options.build_id = gyp_utils.GetBuildNumber()
+    build_id_server_url = os.environ.get('BUILD_ID_SERVER_URL')
+    if build_id_server_url:
+      options.build_id = gyp_utils.GetBuildNumber(
+          version_server=build_id_server_url)
+    else:
+      options.build_id = gyp_utils.GetBuildNumber()
 
   if not options.build_id:
     logging.error('Unable to retrieve build id.')
diff --git a/src/cobalt/content/fonts/BUILD.gn b/src/cobalt/content/fonts/BUILD.gn
index 87b11ff..8b99258 100644
--- a/src/cobalt/content/fonts/BUILD.gn
+++ b/src/cobalt/content/fonts/BUILD.gn
@@ -30,7 +30,7 @@
              "-i",
              rebase_path(font_xml, root_build_dir),
              "-o",
-             outputs[0],
+             rebase_path(outputs[0], root_out_dir),
            ] + package_categories
   }
 
diff --git a/src/cobalt/debug/remote/devtools/copy_devtools_modules.rsp b/src/cobalt/debug/remote/devtools/copy_devtools_modules.rsp
deleted file mode 100644
index 39ad8b2..0000000
--- a/src/cobalt/debug/remote/devtools/copy_devtools_modules.rsp
+++ /dev/null
@@ -1,476 +0,0 @@
-front_end/network/network.js
-front_end/network/SignedExchangeInfoView.js
-front_end/network/ResourceWebSocketFrameView.js
-front_end/network/RequestTimingView.js
-front_end/network/RequestResponseView.js
-front_end/network/RequestPreviewView.js
-front_end/network/RequestInitiatorView.js
-front_end/network/RequestHeadersView.js
-front_end/network/RequestHTMLView.js
-front_end/network/RequestCookiesView.js
-front_end/network/NetworkWaterfallColumn.js
-front_end/network/NetworkTimeCalculator.js
-front_end/network/NetworkSearchScope.js
-front_end/network/NetworkPanel.js
-front_end/network/NetworkOverview.js
-front_end/network/NetworkManageCustomHeadersView.js
-front_end/network/NetworkLogViewColumns.js
-front_end/network/NetworkLogView.js
-front_end/network/NetworkItemView.js
-front_end/network/NetworkFrameGrouper.js
-front_end/network/NetworkDataGridNode.js
-front_end/network/NetworkConfigView.js
-front_end/network/HARWriter.js
-front_end/network/EventSourceMessagesView.js
-front_end/network/BlockedURLsPane.js
-front_end/network/BinaryResourceView.js
-front_end/test_runner/test_runner.js
-front_end/test_runner/TestRunner.js
-front_end/emulation/emulation.js
-front_end/emulation/SensorsView.js
-front_end/emulation/MediaQueryInspector.js
-front_end/emulation/InspectedPagePlaceholder.js
-front_end/emulation/GeolocationsSettingsTab.js
-front_end/emulation/EmulatedDevices.js
-front_end/emulation/DevicesSettingsTab.js
-front_end/emulation/DeviceModeWrapper.js
-front_end/emulation/DeviceModeView.js
-front_end/emulation/DeviceModeToolbar.js
-front_end/emulation/DeviceModeModel.js
-front_end/emulation/AdvancedApp.js
-front_end/inspector_main/inspector_main.js
-front_end/inspector_main/RenderingOptions.js
-front_end/inspector_main/InspectorMain.js
-front_end/js_main/js_main.js
-front_end/js_main/JsMain.js
-front_end/search/search.js
-front_end/search/SearchView.js
-front_end/search/SearchResultsPane.js
-front_end/search/SearchConfig.js
-front_end/screencast/screencast.js
-front_end/screencast/ScreencastView.js
-front_end/screencast/ScreencastApp.js
-front_end/screencast/InputModel.js
-front_end/performance_monitor/performance_monitor.js
-front_end/performance_monitor/PerformanceMonitor.js
-front_end/main/main.js
-front_end/main/SimpleApp.js
-front_end/main/MainImpl.js
-front_end/main/ExecutionContextSelector.js
-front_end/snippets/snippets.js
-front_end/snippets/SnippetsQuickOpen.js
-front_end/snippets/ScriptSnippetFileSystem.js
-front_end/settings/settings.js
-front_end/settings/SettingsScreen.js
-front_end/settings/FrameworkBlackboxSettingsTab.js
-front_end/security/security.js
-front_end/security/SecurityPanel.js
-front_end/security/SecurityModel.js
-front_end/javascript_metadata/javascript_metadata.js
-front_end/javascript_metadata/NativeFunctions.js
-front_end/javascript_metadata/JavaScriptMetadata.js
-front_end/har_importer/har_importer.js
-front_end/har_importer/HARImporter.js
-front_end/har_importer/HARFormat.js
-front_end/browser_debugger/browser_debugger.js
-front_end/browser_debugger/XHRBreakpointsSidebarPane.js
-front_end/browser_debugger/ObjectEventListenersSidebarPane.js
-front_end/browser_debugger/EventListenerBreakpointsSidebarPane.js
-front_end/browser_debugger/DOMBreakpointsSidebarPane.js
-front_end/layer_viewer/layer_viewer.js
-front_end/layer_viewer/TransformController.js
-front_end/layer_viewer/PaintProfilerView.js
-front_end/layer_viewer/Layers3DView.js
-front_end/layer_viewer/LayerViewHost.js
-front_end/layer_viewer/LayerTreeOutline.js
-front_end/layer_viewer/LayerDetailsView.js
-front_end/cm_web_modes/cm_web_modes.js
-front_end/cm_web_modes/cm_web_modes_cm.js
-front_end/cm_web_modes/cm_web_modes_headless.js
-front_end/cm_web_modes/css.js
-front_end/cm_web_modes/javascript.js
-front_end/cm_web_modes/xml.js
-front_end/cm_web_modes/htmlmixed.js
-front_end/cm_web_modes/htmlembedded.js
-front_end/text_editor/text_editor.js
-front_end/text_editor/TextEditorAutocompleteController.js
-front_end/text_editor/CodeMirrorUtils.js
-front_end/text_editor/CodeMirrorTextEditor.js
-front_end/quick_open/quick_open.js
-front_end/quick_open/QuickOpen.js
-front_end/quick_open/HelpQuickOpen.js
-front_end/quick_open/FilteredListWidget.js
-front_end/quick_open/CommandMenu.js
-front_end/elements/elements.js
-front_end/elements/elements-legacy.js
-front_end/elements/StylesSidebarPane.js
-front_end/elements/StylePropertyTreeElement.js
-front_end/elements/StylePropertyHighlighter.js
-front_end/elements/PropertiesWidget.js
-front_end/elements/PlatformFontsWidget.js
-front_end/elements/NodeStackTraceWidget.js
-front_end/elements/MetricsSidebarPane.js
-front_end/elements/MarkerDecorator.js
-front_end/elements/InspectElementModeController.js
-front_end/elements/EventListenersWidget.js
-front_end/elements/ElementsTreeOutline.js
-front_end/elements/ElementsTreeElement.js
-front_end/elements/ElementsTreeElementHighlighter.js
-front_end/elements/ElementStatePaneWidget.js
-front_end/elements/ElementsSidebarPane.js
-front_end/elements/ElementsPanel.js
-front_end/elements/ElementsBreadcrumbs.js
-front_end/elements/DOMPath.js
-front_end/elements/DOMLinkifier.js
-front_end/elements/ComputedStyleWidget.js
-front_end/elements/ComputedStyleModel.js
-front_end/elements/ColorSwatchPopoverIcon.js
-front_end/elements/ClassesPaneWidget.js
-front_end/timeline_model/timeline_model.js
-front_end/timeline_model/TracingLayerTree.js
-front_end/timeline_model/TimelineProfileTree.js
-front_end/timeline_model/TimelineModel.js
-front_end/timeline_model/TimelineModelFilter.js
-front_end/timeline_model/TimelineJSProfile.js
-front_end/timeline_model/TimelineIRModel.js
-front_end/timeline_model/TimelineFrameModel.js
-front_end/help/help.js
-front_end/help/ReleaseNoteView.js
-front_end/help/ReleaseNoteText.js
-front_end/help/HelpImpl.js
-front_end/workspace_diff/workspace_diff.js
-front_end/workspace_diff/WorkspaceDiff.js
-front_end/mobile_throttling/mobile_throttling.js
-front_end/mobile_throttling/ThrottlingSettingsTab.js
-front_end/mobile_throttling/ThrottlingPresets.js
-front_end/mobile_throttling/ThrottlingManager.js
-front_end/mobile_throttling/NetworkThrottlingSelector.js
-front_end/mobile_throttling/NetworkPanelIndicator.js
-front_end/mobile_throttling/MobileThrottlingSelector.js
-front_end/event_listeners/event_listeners.js
-front_end/event_listeners/EventListenersView.js
-front_end/event_listeners/EventListenersUtils.js
-front_end/object_ui/object_ui.js
-front_end/object_ui/RemoteObjectPreviewFormatter.js
-front_end/object_ui/ObjectPropertiesSection.js
-front_end/object_ui/ObjectPopoverHelper.js
-front_end/object_ui/JavaScriptREPL.js
-front_end/object_ui/JavaScriptAutocomplete.js
-front_end/object_ui/CustomPreviewComponent.js
-front_end/cookie_table/cookie_table.js
-front_end/cookie_table/CookiesTable.js
-front_end/cm_modes/cm_modes.js
-front_end/cm_modes/DefaultCodeMirrorMimeMode.js
-front_end/cm_modes/clike.js
-front_end/cm_modes/coffeescript.js
-front_end/cm_modes/php.js
-front_end/cm_modes/python.js
-front_end/cm_modes/shell.js
-front_end/cm_modes/livescript.js
-front_end/cm_modes/markdown.js
-front_end/cm_modes/clojure.js
-front_end/cm_modes/jsx.js
-front_end/css_overview/css_overview.js
-front_end/css_overview/CSSOverviewUnusedDeclarations.js
-front_end/css_overview/CSSOverviewStartView.js
-front_end/css_overview/CSSOverviewSidebarPanel.js
-front_end/css_overview/CSSOverviewProcessingView.js
-front_end/css_overview/CSSOverviewPanel.js
-front_end/css_overview/CSSOverviewModel.js
-front_end/css_overview/CSSOverviewController.js
-front_end/css_overview/CSSOverviewCompletedView.js
-front_end/console/console.js
-front_end/console/ConsoleContextSelector.js
-front_end/console/ConsoleFilter.js
-front_end/console/ConsoleSidebar.js
-front_end/console/ConsolePanel.js
-front_end/console/ConsolePinPane.js
-front_end/console/ConsolePrompt.js
-front_end/console/ConsoleView.js
-front_end/console/ConsoleViewMessage.js
-front_end/console/ConsoleViewport.js
-front_end/source_frame/source_frame.js
-front_end/source_frame/XMLView.js
-front_end/source_frame/SourcesTextEditor.js
-front_end/source_frame/SourceFrame.js
-front_end/source_frame/source_frame.js
-front_end/source_frame/SourceCodeDiff.js
-front_end/source_frame/ResourceSourceFrame.js
-front_end/source_frame/PreviewFactory.js
-front_end/source_frame/JSONView.js
-front_end/source_frame/ImageView.js
-front_end/source_frame/FontView.js
-front_end/source_frame/BinaryResourceViewFactory.js
-front_end/inline_editor/inline_editor.js
-front_end/inline_editor/SwatchPopoverHelper.js
-front_end/inline_editor/CSSShadowModel.js
-front_end/inline_editor/CSSShadowEditor.js
-front_end/inline_editor/ColorSwatch.js
-front_end/inline_editor/BezierUI.js
-front_end/inline_editor/BezierEditor.js
-front_end/diff/diff.js
-front_end/diff/diff_match_patch.js
-front_end/diff/DiffWrapper.js
-front_end/formatter/formatter.js
-front_end/formatter/ScriptFormatter.js
-front_end/formatter/FormatterWorkerPool.js
-front_end/color_picker/color_picker.js
-front_end/color_picker/Spectrum.js
-front_end/color_picker/ContrastOverlay.js
-front_end/color_picker/ContrastInfo.js
-front_end/color_picker/ContrastDetails.js
-front_end/cm/cm.js
-front_end/cm/active-line.js
-front_end/cm/brace-fold.js
-front_end/cm/closebrackets.js
-front_end/cm/codemirror.js
-front_end/cm/comment.js
-front_end/cm/foldcode.js
-front_end/cm/foldgutter.js
-front_end/cm/mark-selection.js
-front_end/cm/matchbrackets.js
-front_end/cm/multiplex.js
-front_end/cm/overlay.js
-front_end/formatter_worker.unbundled.js
-front_end/heap_snapshot_worker.unbundled.js
-front_end/heap_snapshot_model/heap_snapshot_model.js
-front_end/heap_snapshot_model/HeapSnapshotModel.js
-front_end/heap_snapshot_worker/heap_snapshot_worker.js
-front_end/heap_snapshot_worker/AllocationProfile.js
-front_end/heap_snapshot_worker/HeapSnapshot.js
-front_end/heap_snapshot_worker/HeapSnapshotLoader.js
-front_end/heap_snapshot_worker/HeapSnapshotWorker.js
-front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js
-front_end/text_utils/text_utils.js
-front_end/text_utils/TextUtils.js
-front_end/text_utils/TextRange.js
-front_end/text_utils/Text.js
-front_end/formatter_worker/formatter_worker.js
-front_end/formatter_worker/RelaxedJSONParser.js
-front_end/formatter_worker/JavaScriptOutline.js
-front_end/formatter_worker/JavaScriptFormatter.js
-front_end/formatter_worker/IdentityFormatter.js
-front_end/formatter_worker/HTMLFormatter.js
-front_end/formatter_worker/FormatterWorker.js
-front_end/formatter_worker/FormattedContentBuilder.js
-front_end/formatter_worker/ESTreeWalker.js
-front_end/formatter_worker/CSSRuleParser.js
-front_end/formatter_worker/CSSFormatter.js
-front_end/formatter_worker/AcornTokenizer.js
-front_end/cm_headless/cm_headless.js
-front_end/cm_headless/headlesscodemirror.js
-front_end/data_grid/data_grid.js
-front_end/data_grid/ViewportDataGrid.js
-front_end/data_grid/SortableDataGrid.js
-front_end/data_grid/ShowMoreDataGridNode.js
-front_end/data_grid/DataGrid.js
-front_end/protocol_monitor/protocol_monitor.js
-front_end/protocol_monitor/ProtocolMonitor.js
-front_end/console_counters/console_counters.js
-front_end/console_counters/WarningErrorCounter.js
-front_end/extensions/extensions.js
-front_end/extensions/ExtensionAPI.js
-front_end/extensions/ExtensionPanel.js
-front_end/extensions/ExtensionServer.js
-front_end/extensions/ExtensionTraceProvider.js
-front_end/extensions/ExtensionView.js
-front_end/browser_sdk/browser_sdk.js
-front_end/browser_sdk/LogManager.js
-front_end/persistence/persistence.js
-front_end/persistence/WorkspaceSettingsTab.js
-front_end/persistence/PlatformFileSystem.js
-front_end/persistence/PersistenceUtils.js
-front_end/persistence/PersistenceImpl.js
-front_end/persistence/PersistenceActions.js
-front_end/persistence/NetworkPersistenceManager.js
-front_end/persistence/IsolatedFileSystemManager.js
-front_end/persistence/IsolatedFileSystem.js
-front_end/persistence/FileSystemWorkspaceBinding.js
-front_end/persistence/EditFileSystemView.js
-front_end/persistence/Automapping.js
-front_end/components/components.js
-front_end/components/TargetDetachedDialog.js
-front_end/components/Reload.js
-front_end/components/Linkifier.js
-front_end/components/JSPresentationUtils.js
-front_end/components/ImagePreview.js
-front_end/components/DockController.js
-front_end/bindings/bindings.js
-front_end/bindings/TempFile.js
-front_end/bindings/StylesSourceMapping.js
-front_end/bindings/SASSSourceMapping.js
-front_end/bindings/ResourceUtils.js
-front_end/bindings/ResourceScriptMapping.js
-front_end/bindings/ResourceMapping.js
-front_end/bindings/PresentationConsoleMessageHelper.js
-front_end/bindings/NetworkProject.js
-front_end/bindings/LiveLocation.js
-front_end/bindings/FileUtils.js
-front_end/bindings/DefaultScriptMapping.js
-front_end/bindings/DebuggerWorkspaceBinding.js
-front_end/bindings/CSSWorkspaceBinding.js
-front_end/bindings/ContentProviderBasedProject.js
-front_end/bindings/CompilerScriptMapping.js
-front_end/bindings/BreakpointManager.js
-front_end/bindings/BlackboxManager.js
-front_end/workspace/workspace.js
-front_end/workspace/WorkspaceImpl.js
-front_end/workspace/UISourceCode.js
-front_end/workspace/FileManager.js
-front_end/services/services.js
-front_end/services/ServiceManager.js
-front_end/sdk/sdk.js
-front_end/sdk/TracingModel.js
-front_end/sdk/TracingManager.js
-front_end/sdk/TargetManager.js
-front_end/sdk/Target.js
-front_end/sdk/SourceMapManager.js
-front_end/sdk/SourceMap.js
-front_end/sdk/ServiceWorkerManager.js
-front_end/sdk/ServiceWorkerCacheModel.js
-front_end/sdk/ServerTiming.js
-front_end/sdk/SecurityOriginManager.js
-front_end/sdk/SDKModel.js
-front_end/sdk/Script.js
-front_end/sdk/ScreenCaptureModel.js
-front_end/sdk/RuntimeModel.js
-front_end/sdk/ResourceTreeModel.js
-front_end/sdk/Resource.js
-front_end/sdk/RemoteObject.js
-front_end/sdk/ProfileTreeModel.js
-front_end/sdk/IssuesModel.js
-front_end/sdk/PerformanceMetricsModel.js
-front_end/sdk/PaintProfiler.js
-front_end/sdk/OverlayModel.js
-front_end/sdk/NetworkRequest.js
-front_end/sdk/NetworkManager.js
-front_end/sdk/NetworkLog.js
-front_end/sdk/LogModel.js
-front_end/sdk/LayerTreeBase.js
-front_end/sdk/IsolateManager.js
-front_end/sdk/HeapProfilerModel.js
-front_end/sdk/HARLog.js
-front_end/sdk/FilmStripModel.js
-front_end/sdk/EmulationModel.js
-front_end/sdk/DOMModel.js
-front_end/sdk/DOMDebuggerModel.js
-front_end/sdk/DebuggerModel.js
-front_end/sdk/CSSStyleSheetHeader.js
-front_end/sdk/CSSStyleDeclaration.js
-front_end/sdk/CSSRule.js
-front_end/sdk/CSSProperty.js
-front_end/sdk/CSSModel.js
-front_end/sdk/CSSMetadata.js
-front_end/sdk/CSSMedia.js
-front_end/sdk/CSSMatchedStyles.js
-front_end/sdk/CPUProfilerModel.js
-front_end/sdk/CPUProfileDataModel.js
-front_end/sdk/CookieParser.js
-front_end/sdk/CookieModel.js
-front_end/sdk/CompilerSourceMappingContentProvider.js
-front_end/sdk/ConsoleModel.js
-front_end/sdk/Connections.js
-front_end/sdk/ChildTargetManager.js
-front_end/protocol/protocol.js
-front_end/protocol/NodeURL.js
-front_end/protocol/InspectorBackend.js
-front_end/host/host.js
-front_end/host/UserMetrics.js
-front_end/host/ResourceLoader.js
-front_end/host/Platform.js
-front_end/host/InspectorFrontendHost.js
-front_end/host/InspectorFrontendHostAPI.js
-front_end/dom_extension/DOMExtension.js
-front_end/dom_extension/dom_extension.js
-front_end/root.js
-front_end/Runtime.js
-front_end/platform/utilities.js
-front_end/platform/platform.js
-front_end/ui/ARIAUtils.js
-front_end/ui/ZoomManager.js
-front_end/ui/XWidget.js
-front_end/ui/XLink.js
-front_end/ui/XElement.js
-front_end/ui/Widget.js
-front_end/ui/View.js
-front_end/ui/ViewManager.js
-front_end/ui/UIUtils.js
-front_end/ui/ui.js
-front_end/ui/Treeoutline.js
-front_end/ui/Tooltip.js
-front_end/ui/Toolbar.js
-front_end/ui/ThrottledWidget.js
-front_end/ui/TextPrompt.js
-front_end/ui/TextEditor.js
-front_end/ui/TargetCrashedScreen.js
-front_end/ui/TabbedPane.js
-front_end/ui/SyntaxHighlighter.js
-front_end/ui/SuggestBox.js
-front_end/ui/SplitWidget.js
-front_end/ui/SoftDropDown.js
-front_end/ui/SoftContextMenu.js
-front_end/ui/ShortcutsScreen.js
-front_end/ui/ShortcutRegistry.js
-front_end/ui/SettingsUI.js
-front_end/ui/SegmentedButton.js
-front_end/ui/SearchableView.js
-front_end/ui/RootView.js
-front_end/ui/ResizerWidget.js
-front_end/ui/ReportView.js
-front_end/ui/RemoteDebuggingTerminatedScreen.js
-front_end/ui/ProgressIndicator.js
-front_end/ui/PopoverHelper.js
-front_end/ui/Panel.js
-front_end/ui/ListWidget.js
-front_end/ui/ListModel.js
-front_end/ui/ListControl.js
-front_end/ui/KeyboardShortcut.js
-front_end/ui/InspectorView.js
-front_end/ui/InplaceEditor.js
-front_end/ui/Infobar.js
-front_end/ui/Icon.js
-front_end/ui/HistoryInput.js
-front_end/ui/GlassPane.js
-front_end/ui/Geometry.js
-front_end/ui/Fragment.js
-front_end/ui/ForwardedInputEventHandler.js
-front_end/ui/FilterSuggestionBuilder.js
-front_end/ui/FilterBar.js
-front_end/ui/EmptyWidget.js
-front_end/ui/DropTarget.js
-front_end/ui/Dialog.js
-front_end/ui/ContextMenu.js
-front_end/ui/Context.js
-front_end/ui/ARIAUtils.js
-front_end/ui/ActionRegistry.js
-front_end/ui/Action.js
-front_end/ui/ActionDelegate.js
-front_end/ui/ContextFlavorListener.js
-front_end/root.js
-front_end/common/common.js
-front_end/common/common-legacy.js
-front_end/common/App.js
-front_end/common/AppProvider.js
-front_end/common/CharacterIdMap.js
-front_end/common/Color.js
-front_end/common/ContentProvider.js
-front_end/common/EventTarget.js
-front_end/common/JavaScriptMetaData.js
-front_end/common/Linkifier.js
-front_end/common/Object.js
-front_end/common/Console.js
-front_end/common/ParsedURL.js
-front_end/common/Progress.js
-front_end/common/QueryParamHandler.js
-front_end/common/ResourceType.js
-front_end/common/Revealer.js
-front_end/common/Runnable.js
-front_end/common/SegmentedRange.js
-front_end/common/Settings.js
-front_end/common/StaticContentProvider.js
-front_end/common/StringOutputStream.js
-front_end/common/TextDictionary.js
-front_end/common/Throttler.js
-front_end/common/Trie.js
-front_end/common/UIString.js
-front_end/common/Worker.js
diff --git a/src/cobalt/dom/performance.cc b/src/cobalt/dom/performance.cc
index 7554005..8154cc1 100644
--- a/src/cobalt/dom/performance.cc
+++ b/src/cobalt/dom/performance.cc
@@ -76,8 +76,6 @@
       tick_clock_(base::DefaultTickClock::GetInstance()),
       timing_(new PerformanceTiming(clock, time_origin_)),
       memory_(new MemoryInfo()),
-      lifecycle_timing_(
-          new PerformanceLifecycleTiming("lifecycle timing", time_origin_)),
       resource_timing_buffer_size_limit_(
           Performance::kMaxResourceTimingBufferSize),
       resource_timing_buffer_current_size_(0),
@@ -87,6 +85,8 @@
       add_to_performance_entry_buffer_flag_(false) {
   unix_at_zero_monotonic_ = GetUnixAtZeroMonotonic(
       base::DefaultClock::GetInstance(), tick_clock_);
+  lifecycle_timing_ = base::MakeRefCounted<PerformanceLifecycleTiming>(
+      "lifecycle timing", time_origin());
   QueuePerformanceEntry(lifecycle_timing_);
 }
 
diff --git a/src/cobalt/dom/performance_high_resolution_time.h b/src/cobalt/dom/performance_high_resolution_time.h
index 5033e5b..0684e41 100644
--- a/src/cobalt/dom/performance_high_resolution_time.h
+++ b/src/cobalt/dom/performance_high_resolution_time.h
@@ -39,7 +39,7 @@
   return (time - base::TimeTicks()).InMillisecondsF();
 }
 
-// Clamp customized minimum clock resolution.
+// Clamp customized minimum clock resolution in milliseconds.
 //   https://w3c.github.io/hr-time/#clock-resolution
 inline DOMHighResTimeStamp ClampTimeStampMinimumResolution(
     base::TimeTicks ticks,
@@ -49,13 +49,13 @@
         (microseconds % min_resolution_in_microseconds)).InMillisecondsF();
 }
 
-// Clamp customized minimum clock resolution.
+// Clamp customized minimum clock resolution in milliseconds.
 //   https://w3c.github.io/hr-time/#clock-resolution
 inline DOMHighResTimeStamp ClampTimeStampMinimumResolution(base::TimeDelta delta,
     int64_t min_resolution_in_microseconds) {
     int64_t microseconds = delta.InMicroseconds();
     return base::TimeDelta::FromMicroseconds(microseconds -
-        (microseconds % min_resolution_in_microseconds)).InMicrosecondsF();
+        (microseconds % min_resolution_in_microseconds)).InMillisecondsF();
 }
 
 }  // namespace dom
diff --git a/src/cobalt/dom/performance_lifecycle_timing.cc b/src/cobalt/dom/performance_lifecycle_timing.cc
index 08f47d4..f09fee0 100644
--- a/src/cobalt/dom/performance_lifecycle_timing.cc
+++ b/src/cobalt/dom/performance_lifecycle_timing.cc
@@ -41,23 +41,22 @@
   }
 
     DOMHighResTimeStamp ConvertSbTimeMonotonicToDOMHiResTimeStamp(
-      base::TimeTicks time_origin, SbTimeMonotonic monotonic_time) {
+      const DOMHighResTimeStamp time_origin, SbTimeMonotonic monotonic_time) {
     SbTimeMonotonic time_delta = SbTimeGetNow() - SbTimeGetMonotonicNow();
     base::Time base_time = base::Time::FromSbTime(time_delta + monotonic_time);
     base::TimeTicks time_ticks =
         base::TimeTicks::FromInternalValue(static_cast<int64_t>(
             base_time.ToJsTime()));
-    return Performance::MonotonicTimeToDOMHighResTimeStamp(
-        time_origin, time_ticks);
+    return ClampTimeStampMinimumResolution(time_ticks,
+        Performance::kPerformanceTimerMinResolutionInMicroseconds) - time_origin;
   }
 
 }  // namespace
 
 PerformanceLifecycleTiming::PerformanceLifecycleTiming(
-    const std::string& name, base::TimeTicks time_origin)
+    const std::string& name, const DOMHighResTimeStamp time_origin)
     : PerformanceEntry(name, 0.0, 0.0), time_origin_(time_origin) {}
 
-
 DOMHighResTimeStamp PerformanceLifecycleTiming::app_preload() const {
   return ReportDOMHighResTimeStamp(lifecycle_timing_info_.app_preload);
 }
diff --git a/src/cobalt/dom/performance_lifecycle_timing.h b/src/cobalt/dom/performance_lifecycle_timing.h
index 9baa10c..01e3c79 100644
--- a/src/cobalt/dom/performance_lifecycle_timing.h
+++ b/src/cobalt/dom/performance_lifecycle_timing.h
@@ -31,7 +31,7 @@
 class PerformanceLifecycleTiming : public PerformanceEntry {
  public:
   PerformanceLifecycleTiming(const std::string& name,
-                             base::TimeTicks time_origin);
+                             const DOMHighResTimeStamp time_origin);
 
   // Web API.
   DOMHighResTimeStamp app_preload() const;
@@ -83,7 +83,7 @@
 
   LifecycleTimingInfo lifecycle_timing_info_;
 
-  base::TimeTicks time_origin_;
+  DOMHighResTimeStamp time_origin_;
 
   DISALLOW_COPY_AND_ASSIGN(PerformanceLifecycleTiming);
 };
diff --git a/src/cobalt/extension/platform_service.h b/src/cobalt/extension/platform_service.h
index 1d85cc9..4b66e86 100644
--- a/src/cobalt/extension/platform_service.h
+++ b/src/cobalt/extension/platform_service.h
@@ -42,7 +42,7 @@
 
 // When a client receives a message from a service, the service will be passed
 // in as the |context| here, with |data|, which has length |length|.
-typedef void (*ReceiveMessageCallback)(void* context, void* data,
+typedef void (*ReceiveMessageCallback)(void* context, const void* data,
                                        uint64_t length);
 
 typedef struct CobaltExtensionPlatformServiceApi {
diff --git a/src/cobalt/h5vcc/h5vcc_platform_service.cc b/src/cobalt/h5vcc/h5vcc_platform_service.cc
index f744176..8462103 100644
--- a/src/cobalt/h5vcc/h5vcc_platform_service.cc
+++ b/src/cobalt/h5vcc/h5vcc_platform_service.cc
@@ -14,6 +14,9 @@
 
 #include "cobalt/h5vcc/h5vcc_platform_service.h"
 
+#include <utility>
+#include <vector>
+
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/dom/dom_settings.h"
 #include "starboard/common/string.h"
@@ -117,17 +120,23 @@
 }
 
 // static
-void H5vccPlatformService::Receive(void* context, void* data, uint64_t length) {
+void H5vccPlatformService::Receive(void* context, const void* data,
+                                   uint64_t length) {
   DCHECK(context) << "Platform should not call Receive with NULL context";
-  static_cast<H5vccPlatformService*>(context)->ReceiveInternal(data, length);
+  // Make a copy of the data before potentially crossing thread boundaries,
+  // since we don't have any guarantee of the lifetime of the given data.
+  const uint8_t* input_data = static_cast<const uint8_t*>(data);
+  std::vector<uint8_t> internal_data(input_data, input_data + length);
+  static_cast<H5vccPlatformService*>(context)->ReceiveInternal(
+      std::move(internal_data));
 }
 
-void H5vccPlatformService::ReceiveInternal(void* data, uint64_t length) {
+void H5vccPlatformService::ReceiveInternal(std::vector<uint8_t> data) {
   // ReceiveInternal may be called by another thread.
   if (!main_message_loop_->BelongsToCurrentThread()) {
     main_message_loop_->PostTask(
         FROM_HERE, base::Bind(&H5vccPlatformService::ReceiveInternal,
-                              weak_this_, data, length));
+                              weak_this_, std::move(data)));
     return;
   }
   DCHECK(main_message_loop_->BelongsToCurrentThread());
@@ -136,10 +145,11 @@
     return;
   }
   script::Handle<script::ArrayBuffer> data_array_buffer;
-  if (length) {
-    data_array_buffer = script::ArrayBuffer::New(environment_, data, length);
-  } else {
+  if (data.empty()) {
     data_array_buffer = script::ArrayBuffer::New(environment_, 0);
+  } else {
+    data_array_buffer =
+        script::ArrayBuffer::New(environment_, data.data(), data.size());
   }
 
   const scoped_refptr<H5vccPlatformService>& service(this);
diff --git a/src/cobalt/h5vcc/h5vcc_platform_service.h b/src/cobalt/h5vcc/h5vcc_platform_service.h
index 1a86286..62ac3e1 100644
--- a/src/cobalt/h5vcc/h5vcc_platform_service.h
+++ b/src/cobalt/h5vcc/h5vcc_platform_service.h
@@ -17,6 +17,7 @@
 
 #include <map>
 #include <string>
+#include <vector>
 
 #include "base/message_loop/message_loop.h"
 #include "base/optional.h"
@@ -65,9 +66,9 @@
  private:
   static constexpr size_t kMaxNameLength = 1024;
 
-  void ReceiveInternal(void* data, uint64_t length);
+  void ReceiveInternal(std::vector<uint8_t> data);
 
-  static void Receive(void* context, void* data, uint64_t length);
+  static void Receive(void* context, const void* data, uint64_t length);
 
   bool IsOpen();
 
diff --git a/src/cobalt/layout_tests/layout_tests.cc b/src/cobalt/layout_tests/layout_tests.cc
index 028de65..1f25893 100644
--- a/src/cobalt/layout_tests/layout_tests.cc
+++ b/src/cobalt/layout_tests/layout_tests.cc
@@ -128,9 +128,8 @@
   // room for tests to maneuver within and speed at which pixel tests can be
   // done.
   const ViewportSize kDefaultViewportSize(640, 360);
-  ViewportSize viewport_size = test_info.viewport_size
-                                   ? *test_info.viewport_size
-                                   : kDefaultViewportSize;
+  ViewportSize viewport_size =
+      test_info.viewport_size ? *test_info.viewport_size : kDefaultViewportSize;
 
   renderer::RenderTreePixelTester pixel_tester(
       viewport_size.width_height(), GetTestInputRootDirectory(),
@@ -222,30 +221,26 @@
 }
 
 // Cobalt-specific test cases.
-INSTANTIATE_TEST_CASE_P(
-    CobaltSpecificLayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("cobalt")),
-    GetTestName());
+INSTANTIATE_TEST_CASE_P(CobaltSpecificLayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("cobalt")),
+                        GetTestName());
 // Custom CSS 2.1 (https://www.w3.org/TR/CSS21/) test cases.
-INSTANTIATE_TEST_CASE_P(
-    CSS21LayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("css-2-1")),
-    GetTestName());
+INSTANTIATE_TEST_CASE_P(CSS21LayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("css-2-1")),
+                        GetTestName());
 // Custom CSS Background (https://www.w3.org/TR/css3-background/) test cases.
 INSTANTIATE_TEST_CASE_P(
     CSSBackground3LayoutTests, Layout,
     ::testing::ValuesIn(EnumerateLayoutTests("css3-background")),
     GetTestName());
 // Custom CSS Color (https://www.w3.org/TR/css3-color/) test cases.
-INSTANTIATE_TEST_CASE_P(
-    CSSColor3LayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("css3-color")),
-    GetTestName());
+INSTANTIATE_TEST_CASE_P(CSSColor3LayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("css3-color")),
+                        GetTestName());
 // Custom CSS Images (https://www.w3.org/TR/css3-images/) test cases.
 INSTANTIATE_TEST_CASE_P(
     CSSImages3LayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("css3-images")),
-    GetTestName());
+    ::testing::ValuesIn(EnumerateLayoutTests("css3-images")), GetTestName());
 // Custom CSS Media Queries (https://www.w3.org/TR/css3-mediaqueries/) test
 // cases.
 INSTANTIATE_TEST_CASE_P(
@@ -253,16 +248,14 @@
     ::testing::ValuesIn(EnumerateLayoutTests("css3-mediaqueries")),
     GetTestName());
 // Custom CSS Text (https://www.w3.org/TR/css-text-3/) test cases.
-INSTANTIATE_TEST_CASE_P(
-    CSSText3LayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("css-text-3")),
-    GetTestName());
+INSTANTIATE_TEST_CASE_P(CSSText3LayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("css-text-3")),
+                        GetTestName());
 // Custom CSS Transform (http://https://www.w3.org/TR/css-transforms/)
 // test cases.
 INSTANTIATE_TEST_CASE_P(
     CSSTransformsLayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("css-transforms")),
-    GetTestName());
+    ::testing::ValuesIn(EnumerateLayoutTests("css-transforms")), GetTestName());
 // Custom CSS Transition
 // (https://www.w3.org/TR/2013/WD-css3-transitions-20131119/)
 // test cases.
@@ -279,15 +272,13 @@
     GetTestName());
 // Custom bidi text (http://www.unicode.org/reports/tr9/)
 // (https://www.w3.org/TR/CSS21/visuren.html#direction) test cases.
-INSTANTIATE_TEST_CASE_P(
-    BidiLayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("bidi")),
-    GetTestName());
+INSTANTIATE_TEST_CASE_P(BidiLayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("bidi")),
+                        GetTestName());
 // Custom text shaping test cases.
 INSTANTIATE_TEST_CASE_P(
     TextShapingLayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("text-shaping")),
-    GetTestName());
+    ::testing::ValuesIn(EnumerateLayoutTests("text-shaping")), GetTestName());
 // Custom CSS Conditional (https://www.w3.org/TR/css3-conditional/) test cases.
 INSTANTIATE_TEST_CASE_P(
     CSSConditional3LayoutTests, Layout,
@@ -298,25 +289,22 @@
     CSSFlexbox3LayoutTests, Layout,
     ::testing::ValuesIn(EnumerateLayoutTests("css3-flexbox")), GetTestName());
 // Custom CSS Font (https://www.w3.org/TR/css3-fonts/) test cases.
-INSTANTIATE_TEST_CASE_P(
-    CSS3FontsLayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("css3-fonts")),
-    GetTestName());
+INSTANTIATE_TEST_CASE_P(CSS3FontsLayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("css3-fonts")),
+                        GetTestName());
 // Custom CSS Text Decor (https://www.w3.org/TR/css-text-decor-3/) test cases.
 INSTANTIATE_TEST_CASE_P(
     CSS3TextDecorLayoutTests, Layout,
     ::testing::ValuesIn(EnumerateLayoutTests("css3-text-decor")),
     GetTestName());
 // Custom CSS UI (https://www.w3.org/TR/css3-ui/) test cases.
-INSTANTIATE_TEST_CASE_P(
-    CSS3UILayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("css3-ui")),
-    GetTestName());
+INSTANTIATE_TEST_CASE_P(CSS3UILayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("css3-ui")),
+                        GetTestName());
 // Custom CSS Value (https://www.w3.org/TR/css3-values/) test cases.
 INSTANTIATE_TEST_CASE_P(
     CSS3ValuesLayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("css3-values")),
-    GetTestName());
+    ::testing::ValuesIn(EnumerateLayoutTests("css3-values")), GetTestName());
 // Custom incremental layout test cases.
 INSTANTIATE_TEST_CASE_P(
     IncrementalLayoutLayoutTests, Layout,
@@ -324,10 +312,9 @@
     GetTestName());
 // Custom CSSOM view (https://www.w3.org/TR/2013/WD-cssom-view-20131217/)
 // test cases.
-INSTANTIATE_TEST_CASE_P(
-    CSSOMViewLayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("cssom-view")),
-    GetTestName());
+INSTANTIATE_TEST_CASE_P(CSSOMViewLayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("cssom-view")),
+                        GetTestName());
 // Custom DOM (https://dom.spec.whatwg.org/) test cases.
 INSTANTIATE_TEST_CASE_P(DOMLayoutTests, Layout,
                         ::testing::ValuesIn(EnumerateLayoutTests("dom")),
@@ -341,11 +328,9 @@
 
 // JavaScript HTML5 WebAPIs (https://www.w3.org/TR/html50/webappapis.html) test
 // cases.
-INSTANTIATE_TEST_CASE_P(
-    WebAppAPIsLayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("webappapis")),
-    GetTestName());
-
+INSTANTIATE_TEST_CASE_P(WebAppAPIsLayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("webappapis")),
+                        GetTestName());
 // JavaScript HTML5 APIs that describe requestAnimationFrame().
 //   https://www.w3.org/TR/animation-timing/
 INSTANTIATE_TEST_CASE_P(
@@ -356,8 +341,7 @@
 // Problematic test cases found through cluster-fuzz.
 INSTANTIATE_TEST_CASE_P(
     ClusterFuzzLayoutTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("cluster-fuzz")),
-    GetTestName());
+    ::testing::ValuesIn(EnumerateLayoutTests("cluster-fuzz")), GetTestName());
 
 // Intersection Observer API (https://www.w3.org/TR/intersection-observer/) test
 // cases
@@ -366,6 +350,11 @@
     ::testing::ValuesIn(EnumerateLayoutTests("intersection-observer")),
     GetTestName());
 
+// webp background image test cases.
+INSTANTIATE_TEST_CASE_P(WebPLayoutTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("webp")),
+                        GetTestName());
+
 // Blitter does not support Skottie.
 #if !SB_HAS(BLITTER)
 // Lottie (https://github.com/LottieFiles/lottie-player) test cases
@@ -377,17 +366,14 @@
 // Disable on Windows until network stack is implemented.
 #if !defined(COBALT_WIN)
 // Content Security Policy test cases.
-INSTANTIATE_TEST_CASE_P(
-    ContentSecurityPolicyTests, Layout,
-    ::testing::ValuesIn(EnumerateLayoutTests("csp")),
-    GetTestName());
+INSTANTIATE_TEST_CASE_P(ContentSecurityPolicyTests, Layout,
+                        ::testing::ValuesIn(EnumerateLayoutTests("csp")),
+                        GetTestName());
 #endif  // !defined(COBALT_WIN)
 
 // Pixel-perfect tests.
 INSTANTIATE_TEST_CASE_P(
     CobaltPixelTests, LayoutExact,
-    ::testing::ValuesIn(EnumerateLayoutTests("cobalt-pixel")),
-    GetTestName());
-
+    ::testing::ValuesIn(EnumerateLayoutTests("cobalt-pixel")), GetTestName());
 }  // namespace layout_tests
 }  // namespace cobalt
diff --git a/src/cobalt/layout_tests/testdata/webp/layout_tests.txt b/src/cobalt/layout_tests/testdata/webp/layout_tests.txt
new file mode 100644
index 0000000..a7b4e0c
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/webp/layout_tests.txt
@@ -0,0 +1 @@
+static-webp-background-image
diff --git a/src/cobalt/layout_tests/testdata/webp/static-webp-background-image-expected.png b/src/cobalt/layout_tests/testdata/webp/static-webp-background-image-expected.png
new file mode 100644
index 0000000..edcc28c
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/webp/static-webp-background-image-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/webp/static-webp-background-image.html b/src/cobalt/layout_tests/testdata/webp/static-webp-background-image.html
new file mode 100644
index 0000000..92d307b
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/webp/static-webp-background-image.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+ | This test checks if a static webp background image is rendered as expected.
+ -->
+<html>
+
+<head>
+    <style>
+        div {
+            height: 360px;
+            width: 480px;
+        }
+    </style>
+    <script>
+        if (window.testRunner) {
+            window.testRunner.waitUntilDone();
+        }
+
+        var image = new Image();
+        var image_name = 'static-webp-image.webp';
+
+        image.onload = function () {
+            var cobalt = document.getElementById('image');
+            cobalt.style.background = 'url(' + image_name + ')';
+
+            if (window.testRunner) {
+                window.testRunner.notifyDone();
+            }
+        }
+
+        image.src = image_name;
+
+    </script>
+</head>
+
+<body>
+    <div id='image'></div>
+</body>
+
+</html>
diff --git a/src/cobalt/layout_tests/testdata/webp/static-webp-image.webp b/src/cobalt/layout_tests/testdata/webp/static-webp-image.webp
new file mode 100644
index 0000000..cca0a37
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/webp/static-webp-image.webp
Binary files differ
diff --git a/src/cobalt/media_integration_tests/endurance/endurance_test.py b/src/cobalt/media_integration_tests/endurance/endurance_test.py
index 302519d..18cc902 100644
--- a/src/cobalt/media_integration_tests/endurance/endurance_test.py
+++ b/src/cobalt/media_integration_tests/endurance/endurance_test.py
@@ -155,11 +155,11 @@
       app.Resume()
 
     actions = {
-      'PlayPause': lambda _app: _app.PlayOrPause(),
-      'Fastforward': lambda _app: _app.Fastforward(),
-      'Rewind': lambda _app: _app.Rewind(),
-      'PlayPrevious': lambda _app: _app.PlayPrevious(),
-      'PlayNext': lambda _app: _app.PlayNext(),
+        'PlayPause': lambda _app: _app.PlayOrPause(),
+        'Fastforward': lambda _app: _app.Fastforward(),
+        'Rewind': lambda _app: _app.Rewind(),
+        'PlayPrevious': lambda _app: _app.PlayPrevious(),
+        'PlayNext': lambda _app: _app.PlayNext(),
     }
     if TestCase.IsFeatureSupported(Features.SUSPEND_AND_RESUME):
       actions['SuspendAndResume'] = SuspendAndResume
@@ -259,6 +259,6 @@
         if current_running_time - self.last_action_time > IDLE_TIME_MAXIMUM:
           # Play the previous playback again.
           app.PlayPrevious()
-          self.playback_start_time = -1
+          self.last_action_time = current_running_time
 
       app.RemovePlayerStateChangeHandler(self.OnPlayerStateChanged)
diff --git a/src/cobalt/media_session/media_session_client.cc b/src/cobalt/media_session/media_session_client.cc
index 1a18649..99097ef 100644
--- a/src/cobalt/media_session/media_session_client.cc
+++ b/src/cobalt/media_session/media_session_client.cc
@@ -33,6 +33,9 @@
 // Delay to re-query position state after an action has been invoked.
 const base::TimeDelta kUpdateDelay = base::TimeDelta::FromMilliseconds(250);
 
+// Delay to check if the media session state is not active.
+const base::TimeDelta kMaybeFreezeDelay = base::TimeDelta::FromMilliseconds(1500);
+
 // Guess the media position state for the media session.
 void GuessMediaPositionState(MediaSessionState* session_state,
                              const media::WebMediaPlayer** guess_player,
@@ -67,7 +70,8 @@
 
 MediaSessionClient::MediaSessionClient(MediaSession* media_session)
     : media_session_(media_session),
-      platform_playback_state_(kMediaSessionPlaybackStateNone) {
+      platform_playback_state_(kMediaSessionPlaybackStateNone),
+      sequence_number_(0) {
   extension_ = static_cast<const CobaltExtensionMediaSessionApi*>(
       SbSystemGetExtension(kCobaltExtensionMediaSessionName));
   if (extension_) {
@@ -186,6 +190,17 @@
     UpdateMediaSessionState();
   }
 
+  if (!is_active()) {
+    media_session_->task_runner_->PostDelayedTask(
+        FROM_HERE, base::Bind(&MediaSessionClient::RunMaybeFreezeCallback,
+                              base::Unretained(this), ++sequence_number_),
+                              kMaybeFreezeDelay);
+  }
+}
+
+void MediaSessionClient::RunMaybeFreezeCallback(int sequence_number) {
+  if (sequence_number != sequence_number_) return;
+
   if (!is_active() && !maybe_freeze_callback_.is_null()) {
     maybe_freeze_callback_.Run();
   }
diff --git a/src/cobalt/media_session/media_session_client.h b/src/cobalt/media_session/media_session_client.h
index 3e37d1f..115b852 100644
--- a/src/cobalt/media_session/media_session_client.h
+++ b/src/cobalt/media_session/media_session_client.h
@@ -95,6 +95,10 @@
     media_session_ = media_session;
   }
 
+  // If the media session is not active, then run MaybeFreezeCallback to
+  // suspend the App.
+  void RunMaybeFreezeCallback(int sequence_number);
+
  private:
   THREAD_CHECKER(thread_checker_);
   MediaSession* media_session_;
@@ -133,6 +137,10 @@
 
   base::Closure maybe_freeze_callback_;
 
+  // This is for checking the sequence number of PostDelayedTask. It should be
+  // aligned with a single thread.
+  int sequence_number_;
+
   DISALLOW_COPY_AND_ASSIGN(MediaSessionClient);
 };
 
diff --git a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
index a9305ef..076aaf8 100644
--- a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
+++ b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
@@ -20,6 +20,7 @@
 #include <string>
 #include <vector>
 
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "cobalt/extension/graphics.h"
 #include "cobalt/math/size.h"
@@ -364,28 +365,31 @@
       graphics_extension->GetMapToMeshColorAdjustments(&color_adjustment)) {
     // Setup vectors for the color adjustments. Ensure they use dot for decimal
     // point regardless of locale.
-    std::stringstream buffer;
-    buffer.imbue(std::locale::classic());
-    buffer << "  vec4 scale0 = vec4(" << color_adjustment.rgba0_scale[0] << ","
-           << color_adjustment.rgba0_scale[1] << ","
-           << color_adjustment.rgba0_scale[2] << ","
-           << color_adjustment.rgba0_scale[3] << ");";
-    buffer << "  vec4 scale1 = vec4(" << color_adjustment.rgba1_scale[0] << ","
-           << color_adjustment.rgba1_scale[1] << ","
-           << color_adjustment.rgba1_scale[2] << ","
-           << color_adjustment.rgba1_scale[3] << ");";
-    buffer << "  vec4 scale2 = vec4(" << color_adjustment.rgba2_scale[0] << ","
-           << color_adjustment.rgba2_scale[1] << ","
-           << color_adjustment.rgba2_scale[2] << ","
-           << color_adjustment.rgba2_scale[3] << ");";
-    buffer << "  vec4 scale3 = vec4(" << color_adjustment.rgba3_scale[0] << ","
-           << color_adjustment.rgba3_scale[1] << ","
-           << color_adjustment.rgba3_scale[2] << ","
-           << color_adjustment.rgba3_scale[3] << ");";
+    std::string buffer;
+    buffer = "  vec4 scale0 = vec4(" +
+             base::NumberToString(color_adjustment.rgba0_scale[0]) + "," +
+             base::NumberToString(color_adjustment.rgba0_scale[1]) + "," +
+             base::NumberToString(color_adjustment.rgba0_scale[2]) + "," +
+             base::NumberToString(color_adjustment.rgba0_scale[3]) + ");" +
+             "  vec4 scale1 = vec4(" +
+             base::NumberToString(color_adjustment.rgba1_scale[0]) + "," +
+             base::NumberToString(color_adjustment.rgba1_scale[1]) + "," +
+             base::NumberToString(color_adjustment.rgba1_scale[2]) + "," +
+             base::NumberToString(color_adjustment.rgba1_scale[3]) + ");" +
+             "  vec4 scale2 = vec4(" +
+             base::NumberToString(color_adjustment.rgba2_scale[0]) + "," +
+             base::NumberToString(color_adjustment.rgba2_scale[1]) + "," +
+             base::NumberToString(color_adjustment.rgba2_scale[2]) + "," +
+             base::NumberToString(color_adjustment.rgba2_scale[3]) + ");" +
+             "  vec4 scale3 = vec4(" +
+             base::NumberToString(color_adjustment.rgba3_scale[0]) + "," +
+             base::NumberToString(color_adjustment.rgba3_scale[1]) + "," +
+             base::NumberToString(color_adjustment.rgba3_scale[2]) + "," +
+             base::NumberToString(color_adjustment.rgba3_scale[3]) + ");";
     blit_fragment_shader_source +=
         "  vec4 color2 = color * color;"
         "  vec4 color3 = color2 * color;" +
-        buffer.str() +
+        buffer +
         "  color = scale0 + scale1*color + scale2*color2 + scale3*color3;"
         "  gl_FragColor = clamp(color, vec4(0.0), vec4(1.0));"
         "}";
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp b/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
index dfefca6..5fe1b23 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
+++ b/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
@@ -28,6 +28,7 @@
       'target_name': 'skia_library',
       'type': 'static_library',
       'dependencies': [
+        '<(DEPTH)/base/base.gyp:base',
         'skia_library_no_asan',
       ],
       'includes': [
@@ -65,7 +66,6 @@
       'target_name': 'filter_fuzz_stub',
       'type': 'executable',
       'dependencies': [
-        '<(DEPTH)/base/base.gyp:base',
         'skia',
       ],
       'sources': [
diff --git a/src/cobalt/site/docs/development/setup-android.md b/src/cobalt/site/docs/development/setup-android.md
index 61849d8..f999d81 100644
--- a/src/cobalt/site/docs/development/setup-android.md
+++ b/src/cobalt/site/docs/development/setup-android.md
@@ -9,7 +9,7 @@
 ## Preliminary Setup
 
 <aside class="note">
-<b>Note:</b> Before proceeding further, refer to the documentation for <a href="setup-linux.md">"Set up your environment - Linux"</a>. Complete the section **Set up your workstation**, then return and complete the following steps.
+<b>Note:</b> Before proceeding further, refer to the documentation for <a href="setup-linux.html">"Set up your environment - Linux"</a>. Complete the section **Set up your workstation**, then return and complete the following steps.
 </aside>
 
 1.  Additional build dependencies may need to be installed:
@@ -224,7 +224,9 @@
 run that on a device, it needs to be packaged into an APK, which is done by the
 associated "deploy" target (e.g. nplb_deploy). The Starboard test runner does
 all this for you, so just use that to build and run tests. For example, to
-build and run "devel" NPLB on an ARM64 device, from the top 'src' directory:
+build and run "devel" NPLB on an ARM64 device, from the top 'src' directory
+(if you've unnested the 'src' directory, just run this from your top-level
+directory):
 
 ```
 starboard/tools/testing/test_runner.py -p android-arm64 -c devel -b -r -t nplb
diff --git a/src/cobalt/site/docs/development/setup-linux.md b/src/cobalt/site/docs/development/setup-linux.md
index 6b9df7e..9e40a3e 100644
--- a/src/cobalt/site/docs/development/setup-linux.md
+++ b/src/cobalt/site/docs/development/setup-linux.md
@@ -55,10 +55,29 @@
     $ git clone https://cobalt.googlesource.com/cobalt
     ```
 
+### Set up Developer Tools
+
+Cobalt's developer tools require a different file structure which we are in the
+process of moving to. For now, if you want to use these tools, you must unnest
+the `src/` directory like so:
+
+```
+$ cd cobalt
+$ git mv src/* ./
+$ git mv src/.* ./
+```
+
+Once you do that, you'll be able to follow the following two steps to have C++
+and Python linting and formatting as well as other helpful checks enabled. Keep
+in mind that after doing this, you'll want to run following commands in the
+top-level directory instead of the `src/` subdirectory.
+
+Git will track this as a large change, we recommend that you create a commit
+for it and rebase that commit of our upstream continuously for now.
+
 1.  Create a Python 3 virtual environment for working on Cobalt (feel free to use `virtualenvwrapper` instead):
 
     ```
-    $ cd cobalt
     $ python -m venv ~/.virtualenvs/cobalt_dev
     $ source ~/.virtualenvs/cobalt_dev
     $ pip install -r requirements.txt
diff --git a/src/cobalt/site/docs/development/setup-raspi.md b/src/cobalt/site/docs/development/setup-raspi.md
index 75d43cc..0e58a7d 100644
--- a/src/cobalt/site/docs/development/setup-raspi.md
+++ b/src/cobalt/site/docs/development/setup-raspi.md
@@ -54,7 +54,7 @@
 ## Set up your workstation
 
 <aside class="note">
-<b>Note:</b> Before proceeding further, refer to the documentation for <a href="setup-linux.md">"Set up your environment - Linux"</a>. Complete the section **Set up your workstation**, then return and complete the following steps.
+<b>Note:</b> Before proceeding further, refer to the documentation for <a href="setup-linux.html">"Set up your environment - Linux"</a>. Complete the section **Set up your workstation**, then return and complete the following steps.
 </aside>
 
 The following steps install the cross-compiling toolchain on your workstation.
@@ -106,6 +106,11 @@
 
 ## Build, install, and run Cobalt for Raspberry Pi
 
+<aside class="note">
+<b>Note:</b> If you've unnested the 'src' directory, build and compile the code
+in your top-level checkout of Cobalt instead of the 'src' subdirectory.
+</aside>
+
 1.  Build the code by navigating to the src directory in your cobalt directory and run the
     following command :
 
diff --git a/src/cobalt/site/docs/reference/starboard/modules/13/media.md b/src/cobalt/site/docs/reference/starboard/modules/13/media.md
index 9b4d7bb..6b46874 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/13/media.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/13/media.md
@@ -682,24 +682,6 @@
 bool SbMediaIsBufferUsingMemoryPool()
 ```
 
-### SbMediaIsSupported ###
-
-Indicates whether this platform supports decoding `video_codec` and
-`audio_codec` along with decrypting using `key_system`. If `video_codec` is
-`kSbMediaVideoCodecNone` or if `audio_codec` is `kSbMediaAudioCodecNone`, this
-function should return `true` as long as `key_system` is supported on the
-platform to decode any supported input formats.
-
-`video_codec`: The `SbMediaVideoCodec` being checked for platform compatibility.
-`audio_codec`: The `SbMediaAudioCodec` being checked for platform compatibility.
-`key_system`: The key system being checked for platform compatibility.
-
-#### Declaration ####
-
-```
-bool SbMediaIsSupported(SbMediaVideoCodec video_codec, SbMediaAudioCodec audio_codec, const char *key_system)
-```
-
 ### SbMediaSetAudioWriteDuration ###
 
 Communicate to the platform how far past `current_playback_position` the app
diff --git a/src/cobalt/site/docs/reference/starboard/modules/media.md b/src/cobalt/site/docs/reference/starboard/modules/media.md
index 4ad1e16..6b46874 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/media.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/media.md
@@ -682,12 +682,6 @@
 bool SbMediaIsBufferUsingMemoryPool()
 ```
 
-#### Declaration ####
-
-```
-bool SbMediaIsSupported(SbMediaVideoCodec video_codec, SbMediaAudioCodec audio_codec, const char *key_system)
-```
-
 ### SbMediaSetAudioWriteDuration ###
 
 Communicate to the platform how far past `current_playback_position` the app
diff --git a/src/docker-compose.yml b/src/docker-compose.yml
index 19374ed..8b1437b 100644
--- a/src/docker-compose.yml
+++ b/src/docker-compose.yml
@@ -363,6 +363,13 @@
       PLATFORM: linux-x64x11-sbversion-12
       CONFIG: ${CONFIG:-debug}
 
+  # Example usage of unittest:
+  # 1. Build the containers for which you want to unittest
+  # docker-compose up --build --no-start linux-x64x11 unittest
+  # 2. Build the 'all' target for the platform you want to test
+  # PLATFORM=linux-x64x11 CONFIG=devel TARGET=all docker-compose run linux-x64x11
+  # 3. Run the unittests for that target.
+  # PLATFORM=linux-x64x11 CONFIG=devel TARGET=all docker-compose run unittest
   unittest:
     <<: *common-definitions
     build:
diff --git a/src/docker/linux/android/Dockerfile b/src/docker/linux/android/Dockerfile
index 020a826..535b10d 100644
--- a/src/docker/linux/android/Dockerfile
+++ b/src/docker/linux/android/Dockerfile
@@ -18,11 +18,7 @@
     && apt install -qqy --no-install-recommends \
         default-jdk \
         g++-multilib \
-    && apt-get clean autoclean \
-    && apt-get autoremove -y --purge \
-    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
-    && rm -rf /var/lib/{apt,dpkg,cache,log} \
-    && echo "Done"
+    && /opt/clean-after-apt.sh
 
 RUN mkdir -p /root/.android
 
diff --git a/src/docker/linux/base/Dockerfile b/src/docker/linux/base/Dockerfile
index f7e49f2..9cdc8f8 100644
--- a/src/docker/linux/base/Dockerfile
+++ b/src/docker/linux/base/Dockerfile
@@ -14,7 +14,9 @@
 
 ARG BASE_OS
 ARG BASE_OS_TAG
-FROM ${BASE_OS:-gcr.io/cloud-marketplace-containers/google/debian9}:${BASE_OS_TAG:-latest}
+FROM ${BASE_OS:-gcr.io/cloud-marketplace-containers/google/debian10}:${BASE_OS_TAG:-latest}
+
+COPY base/clean-after-apt.sh /opt/clean-after-apt.sh
 
 ENV PYTHONUNBUFFERED 1
 
@@ -28,11 +30,7 @@
         python3-pip \
         python3-requests \
         git ccache \
-        curl \
-    && apt-get clean autoclean \
-    && apt-get autoremove -y --purge \
-    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
-    && rm -rf /var/lib/{apt,dpkg,cache,log} \
-    && echo "Done"
+        curl xz-utils \
+    && /opt/clean-after-apt.sh
 
 CMD ["/usr/bin/python","--version"]
diff --git a/src/docker/linux/base/build/Dockerfile b/src/docker/linux/base/build/Dockerfile
index 0de107d..390b969 100644
--- a/src/docker/linux/base/build/Dockerfile
+++ b/src/docker/linux/base/build/Dockerfile
@@ -26,11 +26,7 @@
         pkgconf \
         unzip \
         yasm \
-    && apt-get clean autoclean \
-    && apt-get autoremove -y --purge \
-    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
-    && rm -rf /var/lib/{apt,dpkg,cache,log} \
-    && echo "Done"
+    && /opt/clean-after-apt.sh
 
 # === Get Nodejs pinned LTS version via NVM
 ARG NVM_SHA256SUM="f068e17dacb88f73302790cc076956c7a0d459ce9b01df842ff3e75744f9e2fe /tmp/install.sh"
diff --git a/src/docker/linux/base/clean-after-apt.sh b/src/docker/linux/base/clean-after-apt.sh
new file mode 100755
index 0000000..c408d58
--- /dev/null
+++ b/src/docker/linux/base/clean-after-apt.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+apt-get clean autoclean
+apt-get autoremove -y --purge
+rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+rm -rf /var/lib/{apt,cache,log}
+echo "Cleaned and purged apt temporaries."
diff --git a/src/docker/linux/clang-3-9/Dockerfile b/src/docker/linux/clang-3-9/Dockerfile
index af62c51..97bab91 100644
--- a/src/docker/linux/clang-3-9/Dockerfile
+++ b/src/docker/linux/clang-3-9/Dockerfile
@@ -18,11 +18,7 @@
 
 RUN apt update -qqy \
     && apt install -qqy --no-install-recommends clang-3.9 \
-    && apt-get clean autoclean \
-    && apt-get autoremove -y --purge \
-    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
-    && rm -rf /var/lib/{apt,dpkg,cache,log} \
-    && echo "Done"
+    && /opt/clean-after-apt.sh
 
 CMD /code/cobalt/build/gyp_cobalt -v -C ${CONFIG} ${PLATFORM} && \
     ccache -z && \
diff --git a/src/docker/linux/evergreen/Dockerfile b/src/docker/linux/evergreen/Dockerfile
index 9880a55a..21223d5 100644
--- a/src/docker/linux/evergreen/Dockerfile
+++ b/src/docker/linux/evergreen/Dockerfile
@@ -21,11 +21,7 @@
         binutils-aarch64-linux-gnu \
         binutils-arm-linux-gnueabi \
         g++-multilib \
-    && apt-get clean autoclean \
-    && apt-get autoremove -y --purge \
-    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
-    && rm -rf /var/lib/{apt,dpkg,cache,log} \
-    && echo "Done"
+    && /opt/clean-after-apt.sh
 
 CMD /code/cobalt/build/gyp_cobalt -v -C ${CONFIG:-debug} ${PLATFORM} && \
     ninja -v -j ${NINJA_PARALLEL} -C ${OUTDIR}/${PLATFORM}_${CONFIG:-debug} ${TARGET:-cobalt_deploy}
diff --git a/src/docker/linux/linux-x64x11/Dockerfile b/src/docker/linux/linux-x64x11/Dockerfile
index 3e8c8dc..816203b 100644
--- a/src/docker/linux/linux-x64x11/Dockerfile
+++ b/src/docker/linux/linux-x64x11/Dockerfile
@@ -27,11 +27,7 @@
         libxrender-dev \
         libxcomposite-dev \
         libxi-dev \
-    && apt-get clean autoclean \
-    && apt-get autoremove -y --purge \
-    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
-    && rm -rf /var/lib/{apt,dpkg,cache,log} \
-    && echo "Done"
+    && /opt/clean-after-apt.sh
 
 CMD /code/cobalt/build/gyp_cobalt -v -C ${CONFIG} ${PLATFORM} && \
     ninja -v -j ${NINJA_PARALLEL} -C ${OUTDIR}/${PLATFORM}_${CONFIG} ${TARGET:-cobalt_deploy}
diff --git a/src/docker/linux/raspi/Dockerfile b/src/docker/linux/raspi/Dockerfile
index e4f7f01..c5d800d 100644
--- a/src/docker/linux/raspi/Dockerfile
+++ b/src/docker/linux/raspi/Dockerfile
@@ -28,11 +28,7 @@
         libxml2 \
         binutils-aarch64-linux-gnu \
         binutils-arm-linux-gnueabi \
-    && apt-get clean autoclean \
-    && apt-get autoremove -y --purge \
-    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
-    && rm -rf /var/lib/{apt,dpkg,cache,log} \
-    && echo "Done"
+    && /opt/clean-after-apt.sh
 
 # Get the combined toolchains package.
 RUN cd /tmp \
diff --git a/src/docker/linux/stub/Dockerfile b/src/docker/linux/stub/Dockerfile
index bf96e84..0237a7c 100644
--- a/src/docker/linux/stub/Dockerfile
+++ b/src/docker/linux/stub/Dockerfile
@@ -14,20 +14,19 @@
 
 FROM cobalt-build-base
 
+# Using clang in the deps here to correctly resolve the appropriate libstdc++.
+# Previously this specifically pulled in libstdc++6-dev which is no longer
+# available since we updated the base image to Debian 10 / Buster.
 RUN apt update -qqy \
     && apt install -qqy --no-install-recommends \
-        libstdc++-6-dev \
+        clang \
         mesa-common-dev \
         libx11-dev \
         libxcomposite-dev \
         libxrender-dev \
         libasound2-dev \
-        libxml2 \
-    && apt-get clean autoclean \
-    && apt-get autoremove -y --purge \
-    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
-    && rm -rf /var/lib/{apt,dpkg,cache,log} \
-    && echo "Done"
+        libxml2-dev \
+    && /opt/clean-after-apt.sh
 
 CMD /code/cobalt/build/gyp_cobalt -v -C ${CONFIG} ${PLATFORM} && \
     ninja -v -j ${NINJA_PARALLEL} -C ${OUTDIR}/${PLATFORM}_${CONFIG} ${TARGET:-cobalt_deploy}
diff --git a/src/docker/linux/unittest/Dockerfile b/src/docker/linux/unittest/Dockerfile
index c833335..45b65f1 100644
--- a/src/docker/linux/unittest/Dockerfile
+++ b/src/docker/linux/unittest/Dockerfile
@@ -17,10 +17,10 @@
 RUN apt update -qqy \
     && apt install -qqy --no-install-recommends \
         libasound2 \
-        libavcodec57 \
-        libavformat57 \
-        libavresample3 \
-        libavutil55 \
+        libavcodec-dev \
+        libavformat-dev \
+        libavresample-dev \
+        libavutil-dev \
         libegl1-mesa \
         libgl1-mesa-dri \
         libgles2-mesa \
@@ -30,14 +30,9 @@
         unzip \
         xauth \
         xvfb \
-    && apt-get clean autoclean \
-    && apt-get autoremove -y --purge \
-    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
-    && rm -rf /var/lib/{apt,dpkg,cache,log} \
-    && echo "Done"
+    && /opt/clean-after-apt.sh
 
 WORKDIR /out
-
 # Sets the locale in the environment. This is needed for NPLB unit tests.
 ENV LANG en_US.UTF-8
 
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioOutputManager.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioOutputManager.java
index 0e1d66b..18418e8 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioOutputManager.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioOutputManager.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.media.AudioAttributes;
+import android.media.AudioDeviceCallback;
 import android.media.AudioDeviceInfo;
 import android.media.AudioFormat;
 import android.media.AudioManager;
@@ -29,12 +30,16 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /** Creates and destroys AudioTrackBridge and handles the volume change. */
 public class AudioOutputManager implements CobaltMediaSession.UpdateVolumeListener {
   private List<AudioTrackBridge> audioTrackBridgeList;
   private Context context;
 
+  AtomicBoolean hasAudioDeviceChanged = new AtomicBoolean(false);
+  boolean hasRegisteredAudioDeviceCallback = false;
+
   public AudioOutputManager(Context context) {
     this.context = context;
     audioTrackBridgeList = new ArrayList<AudioTrackBridge>();
@@ -54,7 +59,7 @@
       int sampleRate,
       int channelCount,
       int preferredBufferSizeInBytes,
-      boolean enableAudioRouting,
+      boolean enableAudioDeviceCallback,
       int tunnelModeAudioSessionId) {
     AudioTrackBridge audioTrackBridge =
         new AudioTrackBridge(
@@ -62,13 +67,58 @@
             sampleRate,
             channelCount,
             preferredBufferSizeInBytes,
-            enableAudioRouting,
             tunnelModeAudioSessionId);
     if (!audioTrackBridge.isAudioTrackValid()) {
       Log.e(TAG, "AudioTrackBridge has invalid audio track");
       return null;
     }
     audioTrackBridgeList.add(audioTrackBridge);
+    hasAudioDeviceChanged.set(false);
+
+    if (Build.VERSION.SDK_INT < 23
+        || hasRegisteredAudioDeviceCallback
+        || !enableAudioDeviceCallback) {
+      return audioTrackBridge;
+    }
+
+    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+    audioManager.registerAudioDeviceCallback(
+        new AudioDeviceCallback() {
+          // Since registering a callback triggers an immediate call to onAudioDevicesAdded() with
+          // current devices, don't set |hasAudioDeviceChanged| for this initial call.
+          private boolean initialDevicesAdded = false;
+
+          private void handleConnectedDeviceChange(AudioDeviceInfo[] devices) {
+            for (AudioDeviceInfo info : devices) {
+              // TODO: Determine if AudioDeviceInfo.TYPE_HDMI_EARC should be checked in API 31.
+              if (info.isSink()
+                  && (info.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP
+                      || info.getType() == AudioDeviceInfo.TYPE_HDMI_ARC
+                      || info.getType() == AudioDeviceInfo.TYPE_HDMI)) {
+                // TODO: Avoid destroying the AudioTrack if the new devices can support the current
+                // AudioFormat.
+                hasAudioDeviceChanged.set(true);
+                break;
+              }
+            }
+          }
+
+          @Override
+          public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
+            if (initialDevicesAdded) {
+              handleConnectedDeviceChange(addedDevices);
+              return;
+            }
+            initialDevicesAdded = true;
+          }
+
+          @Override
+          public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
+            handleConnectedDeviceChange(removedDevices);
+          }
+        },
+        null);
+    hasRegisteredAudioDeviceCallback = true;
     return audioTrackBridge;
   }
 
@@ -307,50 +357,95 @@
               encoding, Build.VERSION.SDK_INT));
       return false;
     }
-    if (hasPassthroughSupportForV23(encoding)) {
+
+    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+    AudioDeviceInfo[] deviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
+
+    // Some devices have issues on reporting playback capability and managing routing when Bluetooth
+    // output is connected.  So e/ac3 support is disabled when Bluetooth output device is connected.
+    for (AudioDeviceInfo info : deviceInfos) {
+      if (info.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP) {
+        Log.i(
+            TAG,
+            String.format(
+                "Passthrough on encoding %d is disabled because Bluetooth output device is"
+                    + " connected.",
+                encoding));
+        return false;
+      }
+    }
+
+    // Sample rate is not provided when the function is called, assume it is 48000.
+    final int DEFAULT_SURROUND_SAMPLE_RATE = 48000;
+
+    if (hasPassthroughSupportForV23(deviceInfos, encoding)) {
       Log.i(
           TAG,
           String.format(
               "Passthrough on encoding %d is supported, as hasPassthroughSupportForV23() returns"
                   + " true.",
               encoding));
-      return true;
-    }
-    if (Build.VERSION.SDK_INT < 29) {
-      Log.i(
-          TAG,
-          String.format(
-              "Passthrough on encoding %d is rejected, as"
-                  + " hasDirectSurroundingPlaybackSupportForV29() is not called for api %d.",
-              encoding, Build.VERSION.SDK_INT));
-      return false;
-    }
-    if (hasDirectSurroundingPlaybackSupportForV29(encoding)) {
-      Log.i(
-          TAG,
-          String.format(
-              "Passthrough on encoding %d is supported, as"
-                  + " hasDirectSurroundingPlaybackSupportForV29() returns true.",
-              encoding));
-      return true;
+    } else {
+      if (Build.VERSION.SDK_INT < 29) {
+        Log.i(
+            TAG,
+            String.format(
+                "Passthrough on encoding %d is rejected, as"
+                    + " hasDirectSurroundPlaybackSupportForV29() is not called for api %d.",
+                encoding, Build.VERSION.SDK_INT));
+        return false;
+      }
+      if (hasDirectSurroundPlaybackSupportForV29(encoding, DEFAULT_SURROUND_SAMPLE_RATE)) {
+        Log.i(
+            TAG,
+            String.format(
+                "Passthrough on encoding %d is supported, as"
+                    + " hasDirectSurroundPlaybackSupportForV29() returns true.",
+                encoding));
+      } else {
+        Log.i(
+            TAG,
+            String.format(
+                "Passthrough on encoding %d is not supported, as"
+                    + " hasDirectSurroundPlaybackSupportForV29() returns false.",
+                encoding));
+        return false;
+      }
     }
 
-    Log.i(
-        TAG,
-        String.format(
-            "Passthrough on encoding %d is not supported, as"
-                + " hasDirectSurroundingPlaybackSupportForV29() returns false.",
-            encoding));
-    return false;
+    Log.i(TAG, "Verify passthrough support by creating an AudioTrack.");
+
+    try {
+      AudioTrack audioTrack =
+          new AudioTrack(
+              getDefaultAudioAttributes(),
+              getPassthroughAudioFormatFor(encoding, DEFAULT_SURROUND_SAMPLE_RATE),
+              AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_5POINT1, encoding),
+              AudioTrack.MODE_STREAM,
+              AudioManager.AUDIO_SESSION_ID_GENERATE);
+      audioTrack.release();
+    } catch (Exception e) {
+      // AudioTrack creation can fail if the audio is routed to an unexpected device. For example,
+      // when the user has Bluetooth headphones connected, or when the encoding is EAC3 and both
+      // HDMI and SPDIF are connected, where the output should fallback to AC3.
+      Log.w(
+          TAG,
+          String.format(
+              "Passthrough on encoding %d is disabled because creating AudioTrack raises"
+                  + " exception: ",
+              encoding),
+          e);
+      return false;
+    }
+
+    Log.i(TAG, "AudioTrack creation succeeded, passthrough support verified.");
+
+    return true;
   }
 
   /** Returns whether passthrough on `encoding` is supported for API 23 and above. */
   @RequiresApi(23)
-  private boolean hasPassthroughSupportForV23(int encoding) {
-    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-    AudioDeviceInfo[] deviceInfos = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
-
-    // TODO: Verify the follow code returns false if non-surrounding BT device is routed.
+  private boolean hasPassthroughSupportForV23(final AudioDeviceInfo[] deviceInfos, int encoding) {
     for (AudioDeviceInfo info : deviceInfos) {
       final int type = info.getType();
       if (type != AudioDeviceInfo.TYPE_HDMI && type != AudioDeviceInfo.TYPE_HDMI_ARC) {
@@ -394,39 +489,50 @@
   }
 
   @RequiresApi(29)
-  /**
-   * Returns whether direct playback on surrounding `encoding` is supported for API 29 and above.
-   */
-  private boolean hasDirectSurroundingPlaybackSupportForV29(int encoding) {
+  /** Returns whether direct playback on surround `encoding` is supported for API 29 and above. */
+  private boolean hasDirectSurroundPlaybackSupportForV29(int encoding, int sampleRate) {
     if (encoding != AudioFormat.ENCODING_AC3
         && encoding != AudioFormat.ENCODING_E_AC3
         && encoding != AudioFormat.ENCODING_E_AC3_JOC) {
       Log.w(
           TAG,
           String.format(
-              "hasDirectSurroundingPlaybackSupportForV29() encountered unsupported encoding %d.",
+              "hasDirectSurroundPlaybackSupportForV29() encountered unsupported encoding %d.",
               encoding));
       return false;
     }
 
-    // Sample rate is not provided when the function is called, assume it is 48000.
-    final int DEFAULT_SURROUNDING_SAMPLE_RATE = 48000;
-    AudioFormat format =
-        new AudioFormat.Builder()
-            .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
-            .setEncoding(encoding)
-            .setSampleRate(DEFAULT_SURROUNDING_SAMPLE_RATE)
-            .build();
-    AudioAttributes attributes =
-        new AudioAttributes.Builder()
-            .setUsage(AudioAttributes.USAGE_MEDIA)
-            .setContentType(AudioAttributes.CONTENT_TYPE_MOVIE)
-            .build();
-    final boolean supported = AudioTrack.isDirectPlaybackSupported(format, attributes);
+    boolean supported =
+        AudioTrack.isDirectPlaybackSupported(
+            getPassthroughAudioFormatFor(encoding, sampleRate), getDefaultAudioAttributes());
     Log.i(
         TAG,
         String.format(
             "isDirectPlaybackSupported() for encoding %d returned %b.", encoding, supported));
     return supported;
   }
+
+  // TODO: Move utility functions into a separate class.
+  /** Returns AudioFormat for surround `encoding` and `sampleRate`. */
+  static AudioFormat getPassthroughAudioFormatFor(int encoding, int sampleRate) {
+    return new AudioFormat.Builder()
+        .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
+        .setEncoding(encoding)
+        .setSampleRate(sampleRate)
+        .build();
+  }
+
+  /** Returns default AudioAttributes for surround playbacks. */
+  static AudioAttributes getDefaultAudioAttributes() {
+    // TODO: Turn this into a static variable after it is moved into a separate class.
+    return new AudioAttributes.Builder()
+        .setUsage(AudioAttributes.USAGE_MEDIA)
+        .setContentType(AudioAttributes.CONTENT_TYPE_MOVIE)
+        .build();
+  }
+
+  @UsedByNative
+  private boolean getAndResetHasAudioDeviceChanged() {
+    return hasAudioDeviceChanged.getAndSet(false);
+  }
 }
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioTrackBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioTrackBridge.java
index 7441984..0001fde 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioTrackBridge.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/AudioTrackBridge.java
@@ -17,11 +17,8 @@
 import static dev.cobalt.media.Log.TAG;
 
 import android.media.AudioAttributes;
-import android.media.AudioDeviceInfo;
 import android.media.AudioFormat;
 import android.media.AudioManager;
-import android.media.AudioRouting;
-import android.media.AudioRouting.OnRoutingChangedListener;
 import android.media.AudioTimestamp;
 import android.media.AudioTrack;
 import android.os.Build;
@@ -30,8 +27,6 @@
 import dev.cobalt.util.UsedByNative;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * A wrapper of the android AudioTrack class. Android AudioTrack would not start playing until the
@@ -51,10 +46,6 @@
   private ByteBuffer avSyncHeader;
   private int avSyncPacketBytesRemaining;
 
-  private AtomicBoolean newAudioDeviceAdded = new AtomicBoolean(false);
-  private AudioDeviceInfo currentRoutedDevice;
-  private OnRoutingChangedListener onRoutingChangedListener;
-
   private static int getBytesPerSample(int audioFormat) {
     switch (audioFormat) {
       case AudioFormat.ENCODING_PCM_16BIT:
@@ -73,10 +64,7 @@
       int sampleRate,
       int channelCount,
       int preferredBufferSizeInBytes,
-      boolean enableAudioRouting,
       int tunnelModeAudioSessionId) {
-    // TODO: Re-enable audio routing when all related bugs are fixed.
-    enableAudioRouting = false;
 
     tunnelModeEnabled = tunnelModeAudioSessionId != -1;
     int channelConfig;
@@ -121,15 +109,15 @@
               .build();
     } else {
       // TODO: Support ENCODING_E_AC3_JOC for api level 28 or later.
-      final boolean is_surrounding =
+      final boolean is_surround =
           sampleType == AudioFormat.ENCODING_AC3 || sampleType == AudioFormat.ENCODING_E_AC3;
-      // TODO: We start to enforce |CONTENT_TYPE_MOVIE| for surrounding playback, investigate if we
-      //       can use |CONTENT_TYPE_MOVIE| for all non-surrounding AudioTrack used by video
+      // TODO: We start to enforce |CONTENT_TYPE_MOVIE| for surround playback, investigate if we
+      //       can use |CONTENT_TYPE_MOVIE| for all non-surround AudioTrack used by video
       //       playback.
       attributes =
           new AudioAttributes.Builder()
               .setContentType(
-                  is_surrounding
+                  is_surround
                       ? AudioAttributes.CONTENT_TYPE_MOVIE
                       : AudioAttributes.CONTENT_TYPE_MUSIC)
               .setUsage(AudioAttributes.USAGE_MEDIA)
@@ -176,31 +164,6 @@
             audioTrackBufferSize,
             preferredBufferSizeInBytes,
             AudioTrack.getMinBufferSize(sampleRate, channelConfig, sampleType)));
-    if (audioTrack != null && enableAudioRouting && Build.VERSION.SDK_INT >= 24) {
-      Log.i(TAG, "Audio routing enabled.");
-      currentRoutedDevice = audioTrack.getRoutedDevice();
-      onRoutingChangedListener =
-          new AudioRouting.OnRoutingChangedListener() {
-            @Override
-            public void onRoutingChanged(AudioRouting router) {
-              AudioDeviceInfo newRoutedDevice = router.getRoutedDevice();
-              if (currentRoutedDevice == null && newRoutedDevice != null) {
-                if (!areAudioDevicesEqual(currentRoutedDevice, newRoutedDevice)) {
-                  Log.v(
-                      TAG,
-                      String.format(
-                          "New audio device %s added to AudioTrackAudioSink.",
-                          newRoutedDevice.getProductName()));
-                  newAudioDeviceAdded.set(true);
-                }
-              }
-              currentRoutedDevice = newRoutedDevice;
-            }
-          };
-      audioTrack.addOnRoutingChangedListener(onRoutingChangedListener, null);
-    } else {
-      Log.i(TAG, "Audio routing disabled.");
-    }
   }
 
   public Boolean isAudioTrackValid() {
@@ -209,9 +172,6 @@
 
   public void release() {
     if (audioTrack != null) {
-      if (Build.VERSION.SDK_INT >= 24 && onRoutingChangedListener != null) {
-        audioTrack.removeOnRoutingChangedListener(onRoutingChangedListener);
-      }
       audioTrack.release();
     }
     audioTrack = null;
@@ -424,26 +384,4 @@
     }
     return audioTrack.getUnderrunCount();
   }
-
-  @RequiresApi(23)
-  private boolean areAudioDevicesEqual(AudioDeviceInfo device1, AudioDeviceInfo device2) {
-    if (device1.getId() == device2.getId()
-        && device1.getType() == device2.getType()
-        && device1.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) {
-      // This is a workaround for the emulator, which triggers an error callback when switching
-      // between devices with different hash codes that are otherwise identical.
-      return Arrays.equals(device1.getChannelCounts(), device2.getChannelCounts())
-          && Arrays.equals(device1.getChannelIndexMasks(), device2.getChannelIndexMasks())
-          && Arrays.equals(device1.getChannelMasks(), device2.getChannelMasks())
-          && Arrays.equals(device1.getEncodings(), device2.getEncodings())
-          && Arrays.equals(device1.getSampleRates(), device2.getSampleRates())
-          && device1.getProductName().equals(device2.getProductName());
-    }
-    return device1.equals(device2);
-  }
-
-  @UsedByNative
-  private boolean getAndResetHasNewAudioDeviceAdded() {
-    return newAudioDeviceAdded.getAndSet(false);
-  }
 }
diff --git a/src/starboard/android/arm/platform_configuration/configuration.gni b/src/starboard/android/arm/platform_configuration/configuration.gni
index 92e7a77..a4cf9ff 100644
--- a/src/starboard/android/arm/platform_configuration/configuration.gni
+++ b/src/starboard/android/arm/platform_configuration/configuration.gni
@@ -15,4 +15,5 @@
 import("//starboard/android/shared/platform_configuration/configuration.gni")
 
 android_abi = "armeabi-v7a"
+arm_version = 7
 sabi_path = "//starboard/sabi/arm/softfp/sabi-v$sb_api_version.json"
diff --git a/src/starboard/android/arm64/platform_configuration/configuration.gni b/src/starboard/android/arm64/platform_configuration/configuration.gni
index 13ca22c..efade93 100644
--- a/src/starboard/android/arm64/platform_configuration/configuration.gni
+++ b/src/starboard/android/arm64/platform_configuration/configuration.gni
@@ -15,4 +15,5 @@
 import("//starboard/android/shared/platform_configuration/configuration.gni")
 
 android_abi = "arm64-v8a"
+arm_version = 8
 sabi_path = "//starboard/sabi/arm64/sabi-v$sb_api_version.json"
diff --git a/src/starboard/android/arm64/vulkan/platform_configuration/configuration.gni b/src/starboard/android/arm64/vulkan/platform_configuration/configuration.gni
index c6d6f73..b90be0f 100644
--- a/src/starboard/android/arm64/vulkan/platform_configuration/configuration.gni
+++ b/src/starboard/android/arm64/vulkan/platform_configuration/configuration.gni
@@ -15,6 +15,7 @@
 import("//starboard/android/shared/platform_configuration/configuration.gni")
 
 android_abi = "arm64-v8a"
+arm_version = 8
 sabi_path = "//starboard/sabi/arm64/sabi-v$sb_api_version.json"
 
 enable_vulkan = true
diff --git a/src/starboard/android/shared/audio_renderer_passthrough.cc b/src/starboard/android/shared/audio_renderer_passthrough.cc
index 4f2820d..1f0849c 100644
--- a/src/starboard/android/shared/audio_renderer_passthrough.cc
+++ b/src/starboard/android/shared/audio_renderer_passthrough.cc
@@ -34,8 +34,6 @@
 constexpr SbTime kAudioTrackUpdateInternal = kSbTimeMillisecond * 5;
 
 constexpr int kPreferredBufferSizeInBytes = 16 * 1024;
-// TODO: Enable audio routing and link it to client side experiment.
-constexpr bool kEnableAudioRouting = false;
 // TODO: Enable passthrough with tunnel mode.
 constexpr int kTunnelModeAudioSessionId = -1;
 
@@ -75,8 +73,10 @@
 
 AudioRendererPassthrough::AudioRendererPassthrough(
     const SbMediaAudioSampleInfo& audio_sample_info,
-    SbDrmSystem drm_system)
-    : audio_sample_info_(audio_sample_info) {
+    SbDrmSystem drm_system,
+    bool enable_audio_device_callback)
+    : audio_sample_info_(audio_sample_info),
+      enable_audio_device_callback_(enable_audio_device_callback) {
   SB_DCHECK(audio_sample_info_.codec == kSbMediaAudioCodecAc3 ||
             audio_sample_info_.codec == kSbMediaAudioCodecEac3);
   if (SbDrmSystemIsValid(drm_system)) {
@@ -384,7 +384,7 @@
       optional<SbMediaAudioSampleType>(),  // Not required in passthrough mode
       audio_sample_info_.number_of_channels,
       audio_sample_info_.samples_per_second, kPreferredBufferSizeInBytes,
-      kEnableAudioRouting, kTunnelModeAudioSessionId));
+      enable_audio_device_callback_, kTunnelModeAudioSessionId));
 
   if (!audio_track_bridge->is_valid()) {
     error_cb_(kSbPlayerErrorDecode, "Error creating AudioTrackBridge");
@@ -436,6 +436,16 @@
   SB_DCHECK(error_cb_);
   SB_DCHECK(audio_track_bridge_);
 
+  if (enable_audio_device_callback_ &&
+      audio_track_bridge_->GetAndResetHasAudioDeviceChanged()) {
+    SB_LOG(INFO) << "Audio device changed, raising a capability changed error "
+                    "to restart playback.";
+    error_cb_(kSbPlayerErrorCapabilityChanged,
+              "Audio device capability changed");
+    audio_track_bridge_->PauseAndFlush();
+    return;
+  }
+
   AudioTrackState current_state;
 
   {
@@ -499,15 +509,21 @@
           sample_buffer, samples_to_write, sync_time);
       // Error code returned as negative value, like kAudioTrackErrorDeadObject.
       if (samples_written < 0) {
-        // `kSbPlayerErrorDecode` is used for general SbPlayer error, there is
-        // no error code corresponding to audio sink.
-        auto error = kSbPlayerErrorDecode;
         if (samples_written == AudioTrackBridge::kAudioTrackErrorDeadObject) {
           // Inform the audio end point change.
-          error = kSbPlayerErrorCapabilityChanged;
+          SB_LOG(INFO)
+              << "Write error for dead audio track, audio device capability "
+                 "has likely changed. Restarting playback.";
+          error_cb_(kSbPlayerErrorCapabilityChanged,
+                    "Audio device capability changed");
+          audio_track_bridge_->PauseAndFlush();
+          return;
         }
-        error_cb_(error, FormatString("Error while writing frames: %d",
-                                      samples_written));
+        // `kSbPlayerErrorDecode` is used for general SbPlayer error, there is
+        // no error code corresponding to audio sink.
+        error_cb_(
+            kSbPlayerErrorDecode,
+            FormatString("Error while writing frames: %d", samples_written));
       }
       decoded_audio_writing_offset_ += samples_written;
 
diff --git a/src/starboard/android/shared/audio_renderer_passthrough.h b/src/starboard/android/shared/audio_renderer_passthrough.h
index 6d9a050..58a073c 100644
--- a/src/starboard/android/shared/audio_renderer_passthrough.h
+++ b/src/starboard/android/shared/audio_renderer_passthrough.h
@@ -49,7 +49,8 @@
       private ::starboard::shared::starboard::player::JobQueue::JobOwner {
  public:
   AudioRendererPassthrough(const SbMediaAudioSampleInfo& audio_sample_info,
-                           SbDrmSystem drm_system);
+                           SbDrmSystem drm_system,
+                           bool enable_audio_device_callback);
   ~AudioRendererPassthrough() override;
 
   bool is_valid() const { return decoder_ != nullptr; }
@@ -96,8 +97,9 @@
   void OnDecoderConsumed();
   void OnDecoderOutput();
 
-  // The following two variables are set in the ctor.
+  // The following three variables are set in the ctor.
   const SbMediaAudioSampleInfo audio_sample_info_;
+  const bool enable_audio_device_callback_;
   // The AudioDecoder is used as a decryptor when the stream is encrypted.
   // TODO: Revisit to encapsulate the AudioDecoder as a SbDrmSystemPrivate
   //       instead.  This would need to turn SbDrmSystemPrivate::Decrypt() into
diff --git a/src/starboard/android/shared/audio_track_audio_sink_type.cc b/src/starboard/android/shared/audio_track_audio_sink_type.cc
index 4c46710..57e9aed 100644
--- a/src/starboard/android/shared/audio_track_audio_sink_type.cc
+++ b/src/starboard/android/shared/audio_track_audio_sink_type.cc
@@ -82,7 +82,7 @@
     SbAudioSinkPrivate::ErrorFunc error_func,
     SbTime start_time,
     int tunnel_mode_audio_session_id,
-    bool enable_audio_routing,
+    bool enable_audio_device_callback,
     void* context)
     : type_(type),
       channels_(channels),
@@ -105,7 +105,7 @@
               channels,
               sampling_frequency_hz,
               preferred_buffer_size_in_bytes,
-              enable_audio_routing,
+              enable_audio_device_callback,
               tunnel_mode_audio_session_id) {
   SB_DCHECK(update_source_status_func_);
   SB_DCHECK(consume_frames_func_);
@@ -178,10 +178,11 @@
   while (!quit_) {
     int playback_head_position = 0;
     SbTime frames_consumed_at = 0;
-    if (bridge_.GetAndResetHasNewAudioDeviceAdded(env)) {
-      SB_LOG(INFO) << "New audio device added.";
-      error_func_(kSbPlayerErrorCapabilityChanged, "New audio device added.",
-                  context_);
+    if (bridge_.GetAndResetHasAudioDeviceChanged(env)) {
+      SB_LOG(INFO) << "Audio device changed, raising a capability changed "
+                      "error to restart playback.";
+      error_func_(kSbPlayerErrorCapabilityChanged,
+                  "Audio device capability changed", context_);
       break;
     }
 
@@ -328,6 +329,7 @@
           capabilities_changed,
           FormatString("Error while writing frames: %d", written_frames),
           context_);
+      SB_LOG(INFO) << "Restarting playback.";
       break;
     } else if (written_frames > 0) {
       last_written_succeeded_at = now;
@@ -418,13 +420,15 @@
     SbAudioSinkPrivate::ErrorFunc error_func,
     void* context) {
   const SbTime kStartTime = 0;
-  const int kTunnelModeAudioSessionId = -1;  // disable tunnel mode
-  const bool kEnableAudioRouting = true;
+  // Disable tunnel mode.
+  const int kTunnelModeAudioSessionId = -1;
+  // Disable AudioDeviceCallback for WebAudio.
+  const bool kEnableAudioDeviceCallback = false;
   return Create(channels, sampling_frequency_hz, audio_sample_type,
                 audio_frame_storage_type, frame_buffers, frames_per_channel,
                 update_source_status_func, consume_frames_func, error_func,
-                kStartTime, kTunnelModeAudioSessionId, kEnableAudioRouting,
-                context);
+                kStartTime, kTunnelModeAudioSessionId,
+                kEnableAudioDeviceCallback, context);
 }
 
 SbAudioSink AudioTrackAudioSinkType::Create(
@@ -439,7 +443,7 @@
     SbAudioSinkPrivate::ErrorFunc error_func,
     SbTime start_media_time,
     int tunnel_mode_audio_session_id,
-    bool enable_audio_routing,
+    bool enable_audio_device_callback,
     void* context) {
   int min_required_frames = SbAudioSinkGetMinBufferSizeInFrames(
       channels, audio_sample_type, sampling_frequency_hz);
@@ -450,8 +454,8 @@
       this, channels, sampling_frequency_hz, audio_sample_type, frame_buffers,
       frames_per_channel, preferred_buffer_size_in_bytes,
       update_source_status_func, consume_frames_func, error_func,
-      start_media_time, tunnel_mode_audio_session_id, enable_audio_routing,
-      context);
+      start_media_time, tunnel_mode_audio_session_id,
+      enable_audio_device_callback, context);
   if (!audio_sink->IsAudioTrackValid()) {
     SB_DLOG(ERROR)
         << "AudioTrackAudioSinkType::Create failed to create audio track";
diff --git a/src/starboard/android/shared/audio_track_audio_sink_type.h b/src/starboard/android/shared/audio_track_audio_sink_type.h
index 5ae9f7b..adf050d 100644
--- a/src/starboard/android/shared/audio_track_audio_sink_type.h
+++ b/src/starboard/android/shared/audio_track_audio_sink_type.h
@@ -68,7 +68,7 @@
       SbAudioSinkPrivate::ErrorFunc error_func,
       SbTime start_time,
       int tunnel_mode_audio_session_id,
-      bool enable_audio_routing,
+      bool enable_audio_device_callback,
       void* context);
 
   bool IsValid(SbAudioSink audio_sink) override {
@@ -111,7 +111,7 @@
       SbAudioSinkPrivate::ErrorFunc error_func,
       SbTime start_media_time,
       int tunnel_mode_audio_session_id,
-      bool enable_audio_routing,
+      bool enable_audio_device_callback,
       void* context);
   ~AudioTrackAudioSink() override;
 
diff --git a/src/starboard/android/shared/audio_track_bridge.cc b/src/starboard/android/shared/audio_track_bridge.cc
index 572e759..79fe83f 100644
--- a/src/starboard/android/shared/audio_track_bridge.cc
+++ b/src/starboard/android/shared/audio_track_bridge.cc
@@ -39,7 +39,7 @@
                                    int channels,
                                    int sampling_frequency_hz,
                                    int preferred_buffer_size_in_bytes,
-                                   bool enable_audio_routing,
+                                   bool enable_audio_device_callback,
                                    int tunnel_mode_audio_session_id) {
   if (coding_type == kSbMediaAudioCodingTypePcm) {
     SB_DCHECK(SbAudioSinkIsAudioSampleTypeSupported(sample_type.value()));
@@ -65,7 +65,7 @@
       j_audio_output_manager.Get(), "createAudioTrackBridge",
       "(IIIIZI)Ldev/cobalt/media/AudioTrackBridge;",
       GetAudioFormatSampleType(coding_type, sample_type), sampling_frequency_hz,
-      channels, preferred_buffer_size_in_bytes, enable_audio_routing,
+      channels, preferred_buffer_size_in_bytes, enable_audio_device_callback,
       tunnel_mode_audio_session_id);
   if (!j_audio_track_bridge) {
     // One of the cases that this may hit is when output happened to be switched
@@ -272,13 +272,17 @@
                                   "J");
 }
 
-bool AudioTrackBridge::GetAndResetHasNewAudioDeviceAdded(
+bool AudioTrackBridge::GetAndResetHasAudioDeviceChanged(
     JniEnvExt* env /*= JniEnvExt::Get()*/) {
   SB_DCHECK(env);
   SB_DCHECK(is_valid());
 
+  ScopedLocalJavaRef<jobject> j_audio_output_manager(
+      env->CallStarboardObjectMethodOrAbort(
+          "getAudioOutputManager", "()Ldev/cobalt/media/AudioOutputManager;"));
+
   return env->CallBooleanMethodOrAbort(
-      j_audio_track_bridge_, "getAndResetHasNewAudioDeviceAdded", "()Z");
+      j_audio_output_manager.Get(), "getAndResetHasAudioDeviceChanged", "()Z");
 }
 
 int AudioTrackBridge::GetUnderrunCount(JniEnvExt* env /*= JniEnvExt::Get()*/) {
diff --git a/src/starboard/android/shared/audio_track_bridge.h b/src/starboard/android/shared/audio_track_bridge.h
index e18e498..607837d 100644
--- a/src/starboard/android/shared/audio_track_bridge.h
+++ b/src/starboard/android/shared/audio_track_bridge.h
@@ -41,7 +41,7 @@
                    int channels,
                    int sampling_frequency_hz,
                    int preferred_buffer_size_in_bytes,
-                   bool enable_audio_routing,
+                   bool enable_audio_device_callback,
                    int tunnel_mode_audio_session_id);
   ~AudioTrackBridge();
 
@@ -79,7 +79,7 @@
   // updated on return.  It can be nullptr.
   int64_t GetPlaybackHeadPosition(SbTime* updated_at,
                                   JniEnvExt* env = JniEnvExt::Get());
-  bool GetAndResetHasNewAudioDeviceAdded(JniEnvExt* env = JniEnvExt::Get());
+  bool GetAndResetHasAudioDeviceChanged(JniEnvExt* env = JniEnvExt::Get());
   int GetUnderrunCount(JniEnvExt* env = JniEnvExt::Get());
 
  private:
diff --git a/src/starboard/android/shared/gyp_configuration.py b/src/starboard/android/shared/gyp_configuration.py
index e38efdf..018dbb6 100644
--- a/src/starboard/android/shared/gyp_configuration.py
+++ b/src/starboard/android/shared/gyp_configuration.py
@@ -277,52 +277,6 @@
   # A map of failing or crashing tests per target.
   __FILTERED_TESTS = {  # pylint: disable=invalid-name
       'player_filter_tests': [
-          # All e/ac3 related decoder tests are disabled.  They will be
-          # re-enabled soon once we can filter out audio decoder tests for
-          # passthrough decoders.
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/12',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/26',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/40',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/54',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/68',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/82',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/84',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/86',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/88',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/90',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/92',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/94',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/96',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/98',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/100',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/102',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.SingleInput/104',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/12',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/26',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/40',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/54',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/68',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/82',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/84',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/86',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/88',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/90',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/92',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/94',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/96',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.MultipleInput/98',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.' +
-              'MultipleInput/100',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.' +
-              'MultipleInput/102',
-          'AdaptiveAudioDecoderTests/AdaptiveAudioDecoderTest.' +
-              'MultipleInput/104',
-          'AudioDecoderTests/AudioDecoderTest.SingleInput/12',
-          'AudioDecoderTests/AudioDecoderTest.ResetBeforeInput/12',
-          'AudioDecoderTests/AudioDecoderTest.MultipleInputs/12',
-          'AudioDecoderTests/AudioDecoderTest.LimitedInput/12',
-          'AudioDecoderTests/AudioDecoderTest.ContinuedLimitedInput/12',
-
           # GetMaxNumberOfCachedFrames() on Android is device dependent,
           # and Android doesn't provide an API to get it. So, this function
           # doesn't make sense on Android. But HoldFramesUntilFull tests depend
diff --git a/src/starboard/android/shared/media_is_audio_supported.cc b/src/starboard/android/shared/media_is_audio_supported.cc
index 334c7dd..e7b04de 100644
--- a/src/starboard/android/shared/media_is_audio_supported.cc
+++ b/src/starboard/android/shared/media_is_audio_supported.cc
@@ -46,17 +46,17 @@
     return false;
   }
   MimeType mime_type(content_type);
-  // Allows for disabling the use of the AudioRouting API to detect when audio
-  // peripherals are connected. Enabled by default.
-  // (https://developer.android.com/reference/android/media/AudioRouting)
-  auto enable_audio_routing_parameter_value =
-      mime_type.GetParamStringValue("enableaudiorouting", "");
-  if (!enable_audio_routing_parameter_value.empty() &&
-      enable_audio_routing_parameter_value != "true" &&
-      enable_audio_routing_parameter_value != "false") {
-    SB_LOG(INFO)
-        << "Invalid value for audio mime parameter \"enableaudiorouting\": "
-        << enable_audio_routing_parameter_value << ".";
+  // Allows for disabling the use of the AudioDeviceCallback API to detect when
+  // audio peripherals are connected. Enabled by default.
+  // (https://developer.android.com/reference/android/media/AudioDeviceCallback)
+  auto enable_audio_device_callback_parameter_value =
+      mime_type.GetParamStringValue("enableaudiodevicecallback", "");
+  if (!enable_audio_device_callback_parameter_value.empty() &&
+      enable_audio_device_callback_parameter_value != "true" &&
+      enable_audio_device_callback_parameter_value != "false") {
+    SB_LOG(INFO) << "Invalid value for audio mime parameter "
+                    "\"enableaudiodevicecallback\": "
+                 << enable_audio_device_callback_parameter_value << ".";
     return false;
   }
   // Allows for enabling tunneled playback. Disabled by default.
@@ -78,6 +78,23 @@
     return false;
   }
 
+  auto audio_passthrough_parameter_value =
+      mime_type.GetParamStringValue("audiopassthrough", "");
+  if (!audio_passthrough_parameter_value.empty() &&
+      audio_passthrough_parameter_value != "true" &&
+      audio_passthrough_parameter_value != "false") {
+    SB_LOG(INFO) << "Invalid value for audio mime parameter "
+                    "\"audiopassthrough\": "
+                 << audio_passthrough_parameter_value
+                 << ". Passthrough is disabled.";
+    return false;
+  }
+  if (audio_passthrough_parameter_value == "false" && is_passthrough) {
+    SB_LOG(INFO) << "Passthrough is rejected because audio mime parameter "
+                    "\"audiopassthrough\" == false.";
+    return false;
+  }
+
   JniEnvExt* env = JniEnvExt::Get();
   ScopedLocalJavaRef<jstring> j_mime(env->NewStringStandardUTFOrAbort(mime));
   const bool must_support_tunnel_mode =
diff --git a/src/starboard/android/shared/player_components_factory.h b/src/starboard/android/shared/player_components_factory.h
index fa64270..b2cbfed 100644
--- a/src/starboard/android/shared/player_components_factory.h
+++ b/src/starboard/android/shared/player_components_factory.h
@@ -64,7 +64,7 @@
 class AudioRendererSinkAndroid : public ::starboard::shared::starboard::player::
                                      filter::AudioRendererSinkImpl {
  public:
-  explicit AudioRendererSinkAndroid(bool enable_audio_routing,
+  explicit AudioRendererSinkAndroid(bool enable_audio_device_callback,
                                     int tunnel_mode_audio_session_id = -1)
       : AudioRendererSinkImpl(
             [=](SbTime start_media_time,
@@ -87,7 +87,8 @@
                   audio_frame_storage_type, frame_buffers,
                   frame_buffers_size_in_frames, update_source_status_func,
                   consume_frames_func, error_func, start_media_time,
-                  tunnel_mode_audio_session_id, enable_audio_routing, context);
+                  tunnel_mode_audio_session_id, enable_audio_device_callback,
+                  context);
             }) {}
 
  private:
@@ -182,9 +183,28 @@
     return (value + alignment - 1) / alignment * alignment;
   }
 
+  static bool IsAudioDeviceCallbackEnabled(
+      const CreationParameters& creation_parameters) {
+    using starboard::shared::starboard::media::MimeType;
+
+    MimeType mime_type(creation_parameters.audio_mime());
+    auto enable_audio_device_callback_parameter_value =
+        mime_type.GetParamStringValue("enableaudiodevicecallback", "");
+    if (enable_audio_device_callback_parameter_value.empty() ||
+        enable_audio_device_callback_parameter_value == "true") {
+      SB_LOG(INFO) << "AudioDeviceCallback is enabled.";
+      return true;
+    }
+    SB_LOG(INFO) << "Mime attribute \"enableaudiodevicecallback\" is set to: "
+                 << enable_audio_device_callback_parameter_value
+                 << ". AudioDeviceCallback is disabled.";
+    return false;
+  }
+
   scoped_ptr<PlayerComponents> CreateComponents(
       const CreationParameters& creation_parameters,
       std::string* error_message) override {
+    using starboard::shared::starboard::media::MimeType;
     SB_DCHECK(error_message);
 
     if (creation_parameters.audio_codec() != kSbMediaAudioCodecAc3 &&
@@ -194,12 +214,21 @@
                                                          error_message);
     }
 
+    MimeType audio_mime_type(creation_parameters.audio_mime());
+    if (audio_mime_type.GetParamStringValue("audiopassthrough", "") ==
+        "false") {
+      SB_LOG(INFO) << "Mime attribute \"audiopassthrough\" is set to: "
+                      "false. Passthrough is disabled.";
+      return scoped_ptr<PlayerComponents>();
+    }
+
     SB_LOG(INFO) << "Creating passthrough components.";
     // TODO: Enable tunnel mode for passthrough
     scoped_ptr<AudioRendererPassthrough> audio_renderer;
     audio_renderer.reset(new AudioRendererPassthrough(
         creation_parameters.audio_sample_info(),
-        GetExtendedDrmSystem(creation_parameters.drm_system())));
+        GetExtendedDrmSystem(creation_parameters.drm_system()),
+        IsAudioDeviceCallbackEnabled(creation_parameters)));
     if (!audio_renderer->is_valid()) {
       return scoped_ptr<PlayerComponents>();
     }
@@ -328,30 +357,20 @@
           creation_parameters.audio_sample_info(),
           GetExtendedDrmSystem(creation_parameters.drm_system()),
           decoder_creator));
-      bool enable_audio_routing = true;
-      MimeType audio_mime_type(creation_parameters.audio_mime());
-      auto enable_audio_routing_parameter_value =
-          audio_mime_type.GetParamStringValue("enableaudiorouting", "");
-      if (enable_audio_routing_parameter_value.empty() ||
-          enable_audio_routing_parameter_value == "true") {
-        SB_LOG(INFO) << "AudioRouting is enabled.";
-      } else {
-        enable_audio_routing = false;
-        SB_LOG(INFO) << "Mime attribute \"enableaudiorouting\" is set to: "
-                     << enable_audio_routing_parameter_value
-                     << ". AudioRouting is disabled.";
-      }
+
+      bool enable_audio_device_callback =
+          IsAudioDeviceCallbackEnabled(creation_parameters);
       if (tunnel_mode_audio_session_id != -1) {
         *audio_renderer_sink = TryToCreateTunnelModeAudioRendererSink(
             tunnel_mode_audio_session_id, creation_parameters,
-            enable_audio_routing);
+            enable_audio_device_callback);
         if (!*audio_renderer_sink) {
           tunnel_mode_audio_session_id = -1;
         }
       }
       if (!*audio_renderer_sink) {
         audio_renderer_sink->reset(
-            new AudioRendererSinkAndroid(enable_audio_routing));
+            new AudioRendererSinkAndroid(enable_audio_device_callback));
       }
     }
 
@@ -523,9 +542,9 @@
   scoped_ptr<AudioRendererSink> TryToCreateTunnelModeAudioRendererSink(
       int tunnel_mode_audio_session_id,
       const CreationParameters& creation_parameters,
-      bool enable_audio_routing) {
+      bool enable_audio_device_callback) {
     scoped_ptr<AudioRendererSink> audio_sink(new AudioRendererSinkAndroid(
-        enable_audio_routing, tunnel_mode_audio_session_id));
+        enable_audio_device_callback, tunnel_mode_audio_session_id));
     // We need to double check if the audio sink can actually be created.
     int max_cached_frames, min_frames_per_append;
     GetAudioRendererParams(creation_parameters, &max_cached_frames,
diff --git a/src/starboard/build/platforms.gni b/src/starboard/build/platforms.gni
index 6a7adcb..b3793c2 100644
--- a/src/starboard/build/platforms.gni
+++ b/src/starboard/build/platforms.gni
@@ -53,4 +53,8 @@
     name = "android-x86"
     path = "starboard/android/x86"
   },
+  {
+    name = "raspi-2"
+    path = "starboard/raspi/2"
+  },
 ]
diff --git a/src/starboard/evergreen/testing/raspi/deploy_cobalt.sh b/src/starboard/evergreen/testing/raspi/deploy_cobalt.sh
index e32b509..6b1b83d 100755
--- a/src/starboard/evergreen/testing/raspi/deploy_cobalt.sh
+++ b/src/starboard/evergreen/testing/raspi/deploy_cobalt.sh
@@ -44,6 +44,9 @@
   echo " Copying loader_app to Cobalt-on-Evergreen directory"
   eval "${SCP} ${OUT}/deploy/loader_app/loader_app pi@${RASPI_ADDR}:/home/pi/coeg/" 1> /dev/null
 
+  echo " Copying crashpad_handler to Cobalt-on-Evergreen directory"
+  eval "${SCP} ${OUT}/deploy/loader_app/crashpad_handler pi@${RASPI_ADDR}:/home/pi/coeg/" 1> /dev/null
+
   echo " Regenerating system image directory"
   eval "${SSH} mkdir -p /home/pi/coeg/content/app/cobalt/lib" 1> /dev/null
 
@@ -53,6 +56,9 @@
   echo " Copying content to system image directory"
   eval "${SCP} -r ${OUT}/deploy/loader_app/content/app/cobalt/content/ pi@${RASPI_ADDR}:/home/pi/coeg/content/app/cobalt/" 1> /dev/null
 
+  echo " Copying fonts to system content directory"
+  eval "${SCP} -r ${OUT}/content/fonts/ pi@${RASPI_ADDR}:/home/pi/coeg/content/" 1> /dev/null
+
   echo " Generating HTML test directory"
   eval "${SSH} mkdir -p /home/pi/coeg/content/app/cobalt/content/web/tests/" 1> /dev/null
 
diff --git a/src/starboard/evergreen/testing/raspi/setup.sh b/src/starboard/evergreen/testing/raspi/setup.sh
index 4135f0a..3292873 100755
--- a/src/starboard/evergreen/testing/raspi/setup.sh
+++ b/src/starboard/evergreen/testing/raspi/setup.sh
@@ -17,7 +17,7 @@
 source $1/../pprint.sh
 source $1/run_command.sh
 
-CACHE_DIR="${HOME}/.cache/cobalt"
+CACHE_DIR="/home/pi/.cache/cobalt"
 CONTENT="/home/pi/coeg/content/app/cobalt/content"
 STORAGE_DIR="/home/pi/.cobalt_storage"
 STORAGE_DIR_TMPFS="${STORAGE_DIR}.tmpfs"
diff --git a/src/starboard/evergreen/testing/tests/crashpad_runs_test.sh b/src/starboard/evergreen/testing/tests/crashpad_runs_test.sh
index f0e1b0a..ebd40ac 100644
--- a/src/starboard/evergreen/testing/tests/crashpad_runs_test.sh
+++ b/src/starboard/evergreen/testing/tests/crashpad_runs_test.sh
@@ -28,7 +28,7 @@
   LOG="${TEST_NAME}.0.log"
   start_cobalt "file:///tests/${TEST_FILE}?channel=tcrash" "${LOG}" LOADER
 
-  if [[ $(ps -C crashpad_handler) -ne 0 ]]; then
+  if [[ $(run_command "ps -C crashpad_handler") -ne 0 ]]; then
     log "error" " Failed to start crashpad_handler"
     return 1
   fi
@@ -54,7 +54,7 @@
     return 1
   fi
 
-  if [[ $(find ${CACHE_DIR}/crashpad_database/completed/ -mmin -3 | ${WC} -l) -eq 0 ]]; then
+  if [[ $(run_command "find ${CACHE_DIR}/crashpad_database/completed/ -mmin -3 | ${WC} -l") -eq 0 ]]; then
     log "error" " Failed upload crash to crash database"
     return 1
   fi
diff --git a/src/starboard/linux/shared/BUILD.gn b/src/starboard/linux/shared/BUILD.gn
index 522b781..9ef03b9 100644
--- a/src/starboard/linux/shared/BUILD.gn
+++ b/src/starboard/linux/shared/BUILD.gn
@@ -398,6 +398,17 @@
   ]
   deps = [ "//third_party/boringssl:crypto" ]
 
+  if (sb_api_version == 12) {
+    sources += [
+      "//starboard/shared/stub/speech_recognizer_cancel.cc",
+      "//starboard/shared/stub/speech_recognizer_create.cc",
+      "//starboard/shared/stub/speech_recognizer_destroy.cc",
+      "//starboard/shared/stub/speech_recognizer_is_supported.cc",
+      "//starboard/shared/stub/speech_recognizer_start.cc",
+      "//starboard/shared/stub/speech_recognizer_stop.cc",
+    ]
+  }
+
   if (is_internal_build) {
     sources += [
       "//starboard/linux/shared/drm_create_system.cc",
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py
index e8a7a9f..4e4a96c 100644
--- a/src/starboard/linux/shared/gyp_configuration.py
+++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -122,7 +122,7 @@
       ],
   }
   # Conditionally disables tests that require ipv6
-  if os.getenv('IPV6_NOT_AVAILABLE', False):
+  if os.getenv('IPV6_AVAILABLE', 1) == '0':
     __FILTERED_TESTS['nplb'] = [
         'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDayDestination/1',
         'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDaySourceForDestination/1',
diff --git a/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc b/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc
index a117f3c..4c7457c 100644
--- a/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc
+++ b/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc
@@ -175,55 +175,57 @@
 TEST(SbMediaCanPlayMimeAndKeySystem, MinimumSupport) {
   // H.264 High Profile Level 4.2
   SbMediaSupportType result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.64402a\"; width=1920; height=1080; "
-      "framerate=30; bitrate=20000",
+      "video/mp4; codecs=\"avc1.64002a\"; width=1920; height=1080; "
+      "framerate=30; bitrate=20000000",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // H.264 Main Profile Level 4.2
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.4d402a\"; width=1920; height=1080; "
+      "video/mp4; codecs=\"avc1.4d002a\"; width=1920; height=1080; "
       "framerate=30;",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.4d402a\"; width=0; height=0; "
+      "video/mp4; codecs=\"avc1.4d002a\"; width=0; height=0; "
       "framerate=0; bitrate=0",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.4d402a\"; width=-0; height=-0; "
+      "video/mp4; codecs=\"avc1.4d002a\"; width=-0; height=-0; "
       "framerate=-0; bitrate=-0",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // H.264 Main Profile Level 2.1
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.4d4015\"; width=432; height=240; "
+      "video/mp4; codecs=\"avc1.4d0015\"; width=432; height=240; "
       "framerate=15;",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // AV1 Main Profile 1080p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"av01.0.05M.08\"; width=1920; height=1080; "
-      "framerate=30; bitrate=20000",
+      "video/mp4; codecs=\"av01.0.09M.08\"; width=1920; height=1080; "
+      "framerate=30; bitrate=20000000",
       "");
 
   // VP9 1080p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/webm; codecs=\"vp9\"; width=1920; height=1080; framerate=60", "");
+      "video/webm; codecs=\"vp9\"; width=1920; height=1080; framerate=60; "
+      "bitrate=20000000",
+      "");
 
   // AAC-LC
   result = SbMediaCanPlayMimeAndKeySystem(
-      "audio/mp4; codecs=\"mp4a.40.2\"; channels=2; bitrate=256;", "");
+      "audio/mp4; codecs=\"mp4a.40.2\"; channels=2; bitrate=256000;", "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // HE-AAC
   result = SbMediaCanPlayMimeAndKeySystem(
-      "audio/mp4; codecs=\"mp4a.40.5\"; channels=2; bitrate=48;", "");
+      "audio/mp4; codecs=\"mp4a.40.5\"; channels=2; bitrate=48000;", "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 }
 
@@ -286,6 +288,7 @@
   }
 }
 
+// TODO: Create an abstraction to shorten the length of this test.
 TEST(SbMediaCanPlayMimeAndKeySystem, PrintMaximumSupport) {
   // AVC
   std::string avc_resolution = "Unsupported";
@@ -298,14 +301,14 @@
     avc_resolution = "1080p";
     // 2K
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"avc1.64402a\"; width=2560; height=1440; "
+        "video/mp4; codecs=\"avc1.64002a\"; width=2560; height=1440; "
         "framerate=30",
         "");
     if (result == kSbMediaSupportTypeProbably) {
       avc_resolution = "2K";
       // 4K
       result = SbMediaCanPlayMimeAndKeySystem(
-          "video/mp4; codecs=\"avc1.64402a\"; width=3840; height=2160; "
+          "video/mp4; codecs=\"avc1.64002a\"; width=3840; height=2160; "
           "framerate=30",
           "");
       if (result == kSbMediaSupportTypeProbably) {
@@ -392,7 +395,7 @@
   // 1080p
   result = SbMediaCanPlayMimeAndKeySystem(
       "video/webm; codecs=\"vp09.02.51.10.01.09.16.09.00\"; width=1920; "
-      "height=1080",
+      "height=1080; framerate=30",
       "");
   if (result == kSbMediaSupportTypeProbably) {
     vp9_hdr_resolution = "1080p";
@@ -418,21 +421,21 @@
   std::string av1_resolution = "Unsupported";
   // 1080p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"av01.0.08M.08\"; width=1920; "
+      "video/mp4; codecs=\"av01.0.09M.08\"; width=1920; "
       "height=1080; framerate=30",
       "");
   if (result == kSbMediaSupportTypeProbably) {
     av1_resolution = "1080p";
     // 2K
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.08M.08\"; width=2560; "
+        "video/mp4; codecs=\"av01.0.12M.08\"; width=2560; "
         "height=1440; framerate=30",
         "");
     if (result == kSbMediaSupportTypeProbably) {
       av1_resolution = "2K";
       // 4K
       result = SbMediaCanPlayMimeAndKeySystem(
-          "video/mp4; codecs=\"av01.0.08M.08\"; width=3840; "
+          "video/mp4; codecs=\"av01.0.12M.08\"; width=3840; "
           "height=2160; framerate=30",
           "");
       if (result == kSbMediaSupportTypeProbably) {
@@ -444,22 +447,22 @@
   std::string av1_hfr_resolution = "Unsupported";
   // 1080p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"av01.0.08M.08\"; width=1920; "
-      "height=1080; framerate=60",
+      "video/mp4; codecs=\"av01.0.09M.08\"; width=1920; height=1080; "
+      "framerate=60",
       "");
   if (result == kSbMediaSupportTypeProbably) {
     av1_hfr_resolution = "1080p";
     // 2K
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.08M.08\"; width=2560; "
-        "height=1440; framerate=60",
+        "video/mp4; codecs=\"av01.0.12M.08\"; width=2560; height=1440; "
+        "framerate=60",
         "");
     if (result == kSbMediaSupportTypeProbably) {
       av1_hfr_resolution = "2K";
       // 4K
       result = SbMediaCanPlayMimeAndKeySystem(
-          "video/mp4; codecs=\"av01.0.08M.08\"; width=3840; "
-          "height=2160; framerate=60",
+          "video/mp4; codecs=\"av01.0.13M.08\"; width=3840; height=2160; "
+          "framerate=60",
           "");
       if (result == kSbMediaSupportTypeProbably) {
         av1_hfr_resolution = "4K";
@@ -472,21 +475,21 @@
   // 1080p
   result = SbMediaCanPlayMimeAndKeySystem(
       "video/mp4; codecs=\"av01.0.09M.10.0.110.09.16.09.0\"; width=1920; "
-      "height=1080; framerate=30",
+      "height=1080",
       "");
   if (result == kSbMediaSupportTypeProbably) {
     av1_hdr_resolution = "1080p";
     // 2K
     result = SbMediaCanPlayMimeAndKeySystem(
         "video/mp4; codecs=\"av01.0.12M.10.0.110.09.16.09.0\"; width=2560; "
-        "height=1440; framerate=30",
+        "height=1440",
         "");
     if (result == kSbMediaSupportTypeProbably) {
       av1_hdr_resolution = "2K";
       // 4K
       result = SbMediaCanPlayMimeAndKeySystem(
           "video/mp4; codecs=\"av01.0.13M.10.0.110.09.16.09.0\"; width=3840; "
-          "height=2160; framerate=30",
+          "height=2160",
           "");
       if (result == kSbMediaSupportTypeProbably) {
         av1_hdr_resolution = "4K";
@@ -514,7 +517,7 @@
   std::string opus_support = "Unsupported";
   result = SbMediaCanPlayMimeAndKeySystem(
       "audio/webm; codecs=\"opus\"; "
-      "channels=2; bitrate=576;",
+      "channels=2; bitrate=128000;",
       "");
   if (result == kSbMediaSupportTypeProbably) {
     opus_support = "Supported";
@@ -524,7 +527,7 @@
   std::string opus51_support = "Unsupported";
   result = SbMediaCanPlayMimeAndKeySystem(
       "audio/webm; codecs=\"opus\"; "
-      "channels=6; bitrate=576;",
+      "channels=6; bitrate=576000;",
       "");
   if (result == kSbMediaSupportTypeProbably) {
     opus51_support = "Supported";
@@ -533,7 +536,7 @@
   // AC-3
   std::string ac3_support = "Unsupported";
   result = SbMediaCanPlayMimeAndKeySystem(
-      "audio/mp4; codecs=\"ac-3\"; channels=2", "");
+      "audio/mp4; codecs=\"ac-3\"; channels=6; bitrate=512000", "");
   if (result == kSbMediaSupportTypeProbably) {
     ac3_support = "Supported";
   }
@@ -541,7 +544,7 @@
   // E-AC-3
   std::string eac3_support = "Unsupported";
   result = SbMediaCanPlayMimeAndKeySystem(
-      "audio/mp4; codecs=\"ec-3\"; channels=2", "");
+      "audio/mp4; codecs=\"ec-3\"; channels=6; bitrate=512000", "");
   if (result == kSbMediaSupportTypeProbably) {
     eac3_support = "Supported";
   }
@@ -561,59 +564,60 @@
                << "\n\tAC-3: " << ac3_support << "\n\tE-AC-3: " << eac3_support;
 }
 
+// TODO: Create an abstraction to shorten the length of this test.
 TEST(SbMediaCanPlayMimeAndKeySystem, ValidateQueriesUnderPeakCapability) {
   // H.264 High Profile Level 4.2 1080p 25 fps
   SbMediaSupportType result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.64402a\"; width=1920; height=1080; "
+      "video/mp4; codecs=\"avc1.64002a\"; width=1920; height=1080; "
       "framerate=25",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // H.264 High Profile Level 4.2 1080p 24 fps
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.64402a\"; width=1920; height=1080; "
+      "video/mp4; codecs=\"avc1.64002a\"; width=1920; height=1080; "
       "framerate=24",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // H.264 High Profile Level 4.2 1920x818
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.64402a\"; width=1920; height=818; "
+      "video/mp4; codecs=\"avc1.64002a\"; width=1920; height=818; "
       "framerate=30",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // H.264 High Profile Level 4.2 720p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.64402a\"; width=1280; height=720; "
+      "video/mp4; codecs=\"avc1.64002a\"; width=1280; height=720; "
       "framerate=30",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // H.264 High Profile Level 4.2 480p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.64402a\"; width=640; height=480; "
+      "video/mp4; codecs=\"avc1.64002a\"; width=640; height=480; "
       "framerate=30",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // H.264 High Profile Level 4.2 360p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.64402a\"; width=480; height=360; "
+      "video/mp4; codecs=\"avc1.64002a\"; width=480; height=360; "
       "framerate=30",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // H.264 High Profile Level 4.2 240p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.64402a\"; width=352; height=240; "
+      "video/mp4; codecs=\"avc1.64002a\"; width=352; height=240; "
       "framerate=30",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
   // H.264 High Profile Level 4.2 144p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"avc1.64402a\"; width=256; height=144; "
+      "video/mp4; codecs=\"avc1.64002a\"; width=256; height=144; "
       "framerate=30",
       "");
   ASSERT_EQ(result, kSbMediaSupportTypeProbably);
@@ -635,78 +639,78 @@
 
   // AV1 Main Profile 4K
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"av01.0.13M.10.0.110.09.16.09.0\"; width=3840; "
-      "height=2160; framerate=30",
+      "video/mp4; codecs=\"av01.0.12M.08\"; width=3840; height=2160; "
+      "framerate=30",
       "");
 
   if (result == kSbMediaSupportTypeProbably) {
     // AV1 Main Profile 1440p
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.12M.10.0.110.09.16.09.0\"; width=2560; "
-        "height=1440; framerate=30",
+        "video/mp4; codecs=\"av01.0.12M.08\"; width=2560; height=1440; "
+        "framerate=30",
         "");
     ASSERT_EQ(result, kSbMediaSupportTypeProbably);
   }
   // AV1 Main Profile 1080p
   result = SbMediaCanPlayMimeAndKeySystem(
-      "video/mp4; codecs=\"av01.0.09M.08.0.110.09.16.09.0\"; width=1920; "
-      "height=1080; framerate=30",
+      "video/mp4; codecs=\"av01.0.09M.08\"; width=1920; height=1080; "
+      "framerate=30",
       "");
 
   if (result == kSbMediaSupportTypeProbably) {
     // AV1 Main Profile 1080p 25 fps
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.09M.08.0.110.09.16.09.0\"; width=1920; "
-        "height=1080; framerate=25",
+        "video/mp4; codecs=\"av01.0.09M.08\"; width=1920; height=1080; "
+        "framerate=25",
         "");
     ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
     // AV1 Main Profile 1080p 24 fps
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.09M.08.0.110.09.16.09.0\"; width=1920; "
-        "height=1080; framerate=24",
+        "video/mp4; codecs=\"av01.0.09M.08\"; width=1920; height=1080; "
+        "framerate=24",
         "");
     ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
     // AV1 Main Profile 1920x818
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.09M.08.0.110.09.16.09.0\"; width=1920; "
-        "height=818; framerate=30",
+        "video/mp4; codecs=\"av01.0.09M.08\"; width=1920; height=818; "
+        "framerate=30",
         "");
     ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
     // AV1 Main Profile 720p
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.08M.10.0.110.09.16.09.0\"; width=1280; "
-        "height=720; framerate=30",
+        "video/mp4; codecs=\"av01.0.05M.08\"; width=1280; height=720; "
+        "framerate=30",
         "");
     ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
     // AV1 Main Profile 480p
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.04M.10.0.110.09.16.09.0\"; width=854; "
-        "height=480; framerate=30",
+        "video/mp4; codecs=\"av01.0.04M.08\"; width=854; height=480; "
+        "framerate=30",
         "");
     ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
     // AV1 Main Profile 360p
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.01M.10.0.110.09.16.09.0\"; width=640; "
-        "height=360; framerate=30",
+        "video/mp4; codecs=\"av01.0.01M.08\"; width=640; height=360; "
+        "framerate=30",
         "");
     ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
     // AV1 Main Profile 240p
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.00M.10.0.110.09.16.09.0\"; width=426; "
-        "height=240; framerate=30",
+        "video/mp4; codecs=\"av01.0.00M.08\"; width=426; height=240; "
+        "framerate=30",
         "");
     ASSERT_EQ(result, kSbMediaSupportTypeProbably);
 
     // AV1 Main Profile 144p
     result = SbMediaCanPlayMimeAndKeySystem(
-        "video/mp4; codecs=\"av01.0.00M.10.0.110.09.16.09.0\"; width=256; "
-        "height=144; framerate=30",
+        "video/mp4; codecs=\"av01.0.00M.08\"; width=256; height=144; "
+        "framerate=30",
         "");
     ASSERT_EQ(result, kSbMediaSupportTypeProbably);
   }
diff --git a/src/starboard/raspi/2/BUILD.gn b/src/starboard/raspi/2/BUILD.gn
new file mode 100644
index 0000000..3cf94e9
--- /dev/null
+++ b/src/starboard/raspi/2/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+static_library("starboard_platform") {
+  check_includes = false
+  configs += [ "//starboard/build/config:starboard_implementation" ]
+
+  public_deps = [ "//starboard/raspi/shared:starboard_platform" ]
+}
diff --git a/src/starboard/raspi/2/platform_configuration/BUILD.gn b/src/starboard/raspi/2/platform_configuration/BUILD.gn
new file mode 100644
index 0000000..ef03b60
--- /dev/null
+++ b/src/starboard/raspi/2/platform_configuration/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+config("platform_configuration") {
+  configs = [
+    "//starboard/build/config/sabi",
+    "//starboard/raspi/shared/platform_configuration",
+  ]
+  cflags = [
+    "-march=armv7-a",
+    "-mfpu=neon-vfpv4",
+    "-mfloat-abi=hard",
+    "-mcpu=cortex-a8",
+    "-mtune=cortex-a8",
+  ]
+}
diff --git a/src/starboard/raspi/2/platform_configuration/configuration.gni b/src/starboard/raspi/2/platform_configuration/configuration.gni
new file mode 100644
index 0000000..77ec5a9
--- /dev/null
+++ b/src/starboard/raspi/2/platform_configuration/configuration.gni
@@ -0,0 +1,20 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//starboard/raspi/shared/platform_configuration/configuration.gni")
+
+arm_float_abi = "hard"
+
+sb_evergreen_compatible_use_libunwind = true
+sb_is_evergreen_compatible = true
diff --git a/src/starboard/raspi/2/toolchain/BUILD.gn b/src/starboard/raspi/2/toolchain/BUILD.gn
new file mode 100644
index 0000000..57a35ca
--- /dev/null
+++ b/src/starboard/raspi/2/toolchain/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/toolchain/gcc_toolchain.gni")
+
+_home_dir = getenv("HOME")
+_clang_base_path = "$_home_dir/starboard-toolchains/x86_64-linux-gnu-clang-chromium-365097-f7e52fbd-8"
+raspi_toolchain_path = "$_home_dir/raspi_tools/tools/arm-bcm2708/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin"
+
+clang_toolchain("host") {
+  clang_base_path = _clang_base_path
+}
+
+gcc_toolchain("target") {
+  cc = "$raspi_toolchain_path/arm-linux-gnueabihf-gcc"
+  cxx = "$raspi_toolchain_path/arm-linux-gnueabihf-g++"
+  ld = cxx
+
+  # We use whatever 'ar' resolves to in gyp.
+  ar = "ar"
+  strip = "$raspi_toolchain_path/arm-linux-gnueabihf-strip"
+
+  toolchain_args = {
+    is_clang = false
+  }
+}
diff --git a/src/starboard/raspi/shared/BUILD.gn b/src/starboard/raspi/shared/BUILD.gn
new file mode 100644
index 0000000..37c97e7
--- /dev/null
+++ b/src/starboard/raspi/shared/BUILD.gn
@@ -0,0 +1,412 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import("//starboard/shared/starboard/player/buildfiles.gni")
+
+group("starboard_platform") {
+  public_deps = [ ":starboard_platform_sources" ]
+}
+
+static_library("starboard_platform_sources") {
+  sources = [
+    "//starboard/linux/shared/atomic_public.h",
+    "//starboard/linux/shared/configuration_constants.cc",
+    "//starboard/linux/shared/configuration_public.h",
+    "//starboard/linux/shared/netlink.cc",
+    "//starboard/linux/shared/netlink.h",
+    "//starboard/linux/shared/routes.cc",
+    "//starboard/linux/shared/routes.h",
+    "//starboard/linux/shared/system_get_connection_type.cc",
+    "//starboard/linux/shared/system_get_path.cc",
+    "//starboard/linux/shared/system_has_capability.cc",
+    "//starboard/raspi/shared/application_dispmanx.cc",
+    "//starboard/raspi/shared/audio_sink_type_dispatcher.cc",
+    "//starboard/raspi/shared/configuration.cc",
+    "//starboard/raspi/shared/configuration.h",
+    "//starboard/raspi/shared/dispmanx_util.cc",
+    "//starboard/raspi/shared/dispmanx_util.h",
+    "//starboard/raspi/shared/graphics.cc",
+    "//starboard/raspi/shared/graphics.h",
+    "//starboard/raspi/shared/main.cc",
+    "//starboard/raspi/shared/media_is_video_supported.cc",
+    "//starboard/raspi/shared/open_max/decode_target_create.cc",
+    "//starboard/raspi/shared/open_max/decode_target_create.h",
+    "//starboard/raspi/shared/open_max/decode_target_get_info.cc",
+    "//starboard/raspi/shared/open_max/decode_target_internal.h",
+    "//starboard/raspi/shared/open_max/decode_target_release.cc",
+    "//starboard/raspi/shared/open_max/dispmanx_resource_pool.cc",
+    "//starboard/raspi/shared/open_max/dispmanx_resource_pool.h",
+    "//starboard/raspi/shared/open_max/image_decode.cc",
+    "//starboard/raspi/shared/open_max/image_is_decode_supported.cc",
+    "//starboard/raspi/shared/open_max/open_max_component.cc",
+    "//starboard/raspi/shared/open_max/open_max_component.h",
+    "//starboard/raspi/shared/open_max/open_max_component_base.cc",
+    "//starboard/raspi/shared/open_max/open_max_component_base.h",
+    "//starboard/raspi/shared/open_max/open_max_egl_render_component.cc",
+    "//starboard/raspi/shared/open_max/open_max_egl_render_component.h",
+    "//starboard/raspi/shared/open_max/open_max_image_decode_component.cc",
+    "//starboard/raspi/shared/open_max/open_max_image_decode_component.h",
+    "//starboard/raspi/shared/open_max/open_max_video_decode_component.cc",
+    "//starboard/raspi/shared/open_max/open_max_video_decode_component.h",
+    "//starboard/raspi/shared/open_max/video_decoder.cc",
+    "//starboard/raspi/shared/open_max/video_decoder.h",
+    "//starboard/raspi/shared/player_components_factory.cc",
+    "//starboard/raspi/shared/system_get_device_type.cc",
+    "//starboard/raspi/shared/system_get_extensions.cc",
+    "//starboard/raspi/shared/system_get_property.cc",
+    "//starboard/raspi/shared/system_gles2.cc",
+    "//starboard/raspi/shared/thread_create_priority.cc",
+    "//starboard/raspi/shared/video_renderer_sink_impl.cc",
+    "//starboard/raspi/shared/video_renderer_sink_impl.h",
+    "//starboard/raspi/shared/window_create.cc",
+    "//starboard/raspi/shared/window_destroy.cc",
+    "//starboard/raspi/shared/window_get_platform_handle.cc",
+    "//starboard/raspi/shared/window_get_size.cc",
+    "//starboard/raspi/shared/window_internal.cc",
+    "//starboard/shared/alsa/alsa_audio_sink_type.cc",
+    "//starboard/shared/alsa/alsa_audio_sink_type.h",
+    "//starboard/shared/alsa/alsa_util.cc",
+    "//starboard/shared/alsa/alsa_util.h",
+    "//starboard/shared/dlmalloc/memory_map.cc",
+    "//starboard/shared/dlmalloc/memory_protect.cc",
+    "//starboard/shared/dlmalloc/memory_unmap.cc",
+    "//starboard/shared/egl/system_egl.cc",
+    "//starboard/shared/gcc/atomic_gcc_public.h",
+    "//starboard/shared/iso/character_is_alphanumeric.cc",
+    "//starboard/shared/iso/character_is_digit.cc",
+    "//starboard/shared/iso/character_is_hex_digit.cc",
+    "//starboard/shared/iso/character_is_space.cc",
+    "//starboard/shared/iso/character_is_upper.cc",
+    "//starboard/shared/iso/character_to_lower.cc",
+    "//starboard/shared/iso/character_to_upper.cc",
+    "//starboard/shared/iso/directory_close.cc",
+    "//starboard/shared/iso/directory_get_next.cc",
+    "//starboard/shared/iso/directory_open.cc",
+    "//starboard/shared/iso/double_absolute.cc",
+    "//starboard/shared/iso/double_exponent.cc",
+    "//starboard/shared/iso/double_floor.cc",
+    "//starboard/shared/iso/double_is_finite.cc",
+    "//starboard/shared/iso/double_is_nan.cc",
+    "//starboard/shared/iso/memory_allocate_unchecked.cc",
+    "//starboard/shared/iso/memory_compare.cc",
+    "//starboard/shared/iso/memory_copy.cc",
+    "//starboard/shared/iso/memory_find_byte.cc",
+    "//starboard/shared/iso/memory_free.cc",
+    "//starboard/shared/iso/memory_move.cc",
+    "//starboard/shared/iso/memory_reallocate_unchecked.cc",
+    "//starboard/shared/iso/memory_set.cc",
+    "//starboard/shared/iso/string_compare.cc",
+    "//starboard/shared/iso/string_compare_all.cc",
+    "//starboard/shared/iso/string_find_character.cc",
+    "//starboard/shared/iso/string_find_last_character.cc",
+    "//starboard/shared/iso/string_find_string.cc",
+    "//starboard/shared/iso/string_get_length.cc",
+    "//starboard/shared/iso/string_get_length_wide.cc",
+    "//starboard/shared/iso/string_parse_double.cc",
+    "//starboard/shared/iso/string_parse_signed_integer.cc",
+    "//starboard/shared/iso/string_parse_uint64.cc",
+    "//starboard/shared/iso/string_parse_unsigned_integer.cc",
+    "//starboard/shared/iso/string_scan.cc",
+    "//starboard/shared/iso/system_binary_search.cc",
+    "//starboard/shared/iso/system_sort.cc",
+    "//starboard/shared/libevent/socket_waiter_add.cc",
+    "//starboard/shared/libevent/socket_waiter_create.cc",
+    "//starboard/shared/libevent/socket_waiter_destroy.cc",
+    "//starboard/shared/libevent/socket_waiter_internal.cc",
+    "//starboard/shared/libevent/socket_waiter_remove.cc",
+    "//starboard/shared/libevent/socket_waiter_wait.cc",
+    "//starboard/shared/libevent/socket_waiter_wait_timed.cc",
+    "//starboard/shared/libevent/socket_waiter_wake_up.cc",
+    "//starboard/shared/linux/byte_swap.cc",
+    "//starboard/shared/linux/cpu_features_get.cc",
+    "//starboard/shared/linux/dev_input/dev_input.cc",
+    "//starboard/shared/linux/get_home_directory.cc",
+    "//starboard/shared/linux/memory_get_stack_bounds.cc",
+    "//starboard/shared/linux/page_internal.cc",
+    "//starboard/shared/linux/socket_get_interface_address.cc",
+    "//starboard/shared/linux/system_get_random_data.cc",
+    "//starboard/shared/linux/system_get_stack.cc",
+    "//starboard/shared/linux/system_get_total_cpu_memory.cc",
+    "//starboard/shared/linux/system_get_used_cpu_memory.cc",
+    "//starboard/shared/linux/system_is_debugger_attached.cc",
+    "//starboard/shared/linux/system_symbolize.cc",
+    "//starboard/shared/linux/thread_get_id.cc",
+    "//starboard/shared/linux/thread_get_name.cc",
+    "//starboard/shared/linux/thread_set_name.cc",
+    "//starboard/shared/nouser/user_get_current.cc",
+    "//starboard/shared/nouser/user_get_property.cc",
+    "//starboard/shared/nouser/user_get_signed_in.cc",
+    "//starboard/shared/nouser/user_internal.cc",
+    "//starboard/shared/opus/opus_audio_decoder.cc",
+    "//starboard/shared/opus/opus_audio_decoder.h",
+    "//starboard/shared/posix/directory_create.cc",
+    "//starboard/shared/posix/file_atomic_replace.cc",
+    "//starboard/shared/posix/file_can_open.cc",
+    "//starboard/shared/posix/file_close.cc",
+    "//starboard/shared/posix/file_delete.cc",
+    "//starboard/shared/posix/file_exists.cc",
+    "//starboard/shared/posix/file_flush.cc",
+    "//starboard/shared/posix/file_get_info.cc",
+    "//starboard/shared/posix/file_get_path_info.cc",
+    "//starboard/shared/posix/file_open.cc",
+    "//starboard/shared/posix/file_read.cc",
+    "//starboard/shared/posix/file_seek.cc",
+    "//starboard/shared/posix/file_truncate.cc",
+    "//starboard/shared/posix/file_write.cc",
+    "//starboard/shared/posix/log.cc",
+    "//starboard/shared/posix/log_flush.cc",
+    "//starboard/shared/posix/log_format.cc",
+    "//starboard/shared/posix/log_is_tty.cc",
+    "//starboard/shared/posix/log_raw.cc",
+    "//starboard/shared/posix/memory_allocate_aligned_unchecked.cc",
+    "//starboard/shared/posix/memory_flush.cc",
+    "//starboard/shared/posix/memory_free_aligned.cc",
+    "//starboard/shared/posix/set_non_blocking_internal.cc",
+    "//starboard/shared/posix/socket_accept.cc",
+    "//starboard/shared/posix/socket_bind.cc",
+    "//starboard/shared/posix/socket_clear_last_error.cc",
+    "//starboard/shared/posix/socket_connect.cc",
+    "//starboard/shared/posix/socket_create.cc",
+    "//starboard/shared/posix/socket_destroy.cc",
+    "//starboard/shared/posix/socket_free_resolution.cc",
+    "//starboard/shared/posix/socket_get_last_error.cc",
+    "//starboard/shared/posix/socket_get_local_address.cc",
+    "//starboard/shared/posix/socket_internal.cc",
+    "//starboard/shared/posix/socket_is_connected.cc",
+    "//starboard/shared/posix/socket_is_connected_and_idle.cc",
+    "//starboard/shared/posix/socket_is_ipv6_supported.cc",
+    "//starboard/shared/posix/socket_join_multicast_group.cc",
+    "//starboard/shared/posix/socket_listen.cc",
+    "//starboard/shared/posix/socket_receive_from.cc",
+    "//starboard/shared/posix/socket_resolve.cc",
+    "//starboard/shared/posix/socket_send_to.cc",
+    "//starboard/shared/posix/socket_set_broadcast.cc",
+    "//starboard/shared/posix/socket_set_receive_buffer_size.cc",
+    "//starboard/shared/posix/socket_set_reuse_address.cc",
+    "//starboard/shared/posix/socket_set_send_buffer_size.cc",
+    "//starboard/shared/posix/socket_set_tcp_keep_alive.cc",
+    "//starboard/shared/posix/socket_set_tcp_no_delay.cc",
+    "//starboard/shared/posix/socket_set_tcp_window_scaling.cc",
+    "//starboard/shared/posix/storage_write_record.cc",
+    "//starboard/shared/posix/string_compare_no_case.cc",
+    "//starboard/shared/posix/string_compare_no_case_n.cc",
+    "//starboard/shared/posix/string_compare_wide.cc",
+    "//starboard/shared/posix/string_format.cc",
+    "//starboard/shared/posix/string_format_wide.cc",
+    "//starboard/shared/posix/system_break_into_debugger.cc",
+    "//starboard/shared/posix/system_clear_last_error.cc",
+    "//starboard/shared/posix/system_get_error_string.cc",
+    "//starboard/shared/posix/system_get_last_error.cc",
+    "//starboard/shared/posix/system_get_locale_id.cc",
+    "//starboard/shared/posix/system_get_number_of_processors.cc",
+    "//starboard/shared/posix/thread_sleep.cc",
+    "//starboard/shared/posix/time_get_monotonic_now.cc",
+    "//starboard/shared/posix/time_get_monotonic_thread_now.cc",
+    "//starboard/shared/posix/time_get_now.cc",
+    "//starboard/shared/posix/time_is_time_thread_now_supported.cc",
+    "//starboard/shared/posix/time_zone_get_current.cc",
+    "//starboard/shared/posix/time_zone_get_name.cc",
+    "//starboard/shared/pthread/condition_variable_broadcast.cc",
+    "//starboard/shared/pthread/condition_variable_create.cc",
+    "//starboard/shared/pthread/condition_variable_destroy.cc",
+    "//starboard/shared/pthread/condition_variable_signal.cc",
+    "//starboard/shared/pthread/condition_variable_wait.cc",
+    "//starboard/shared/pthread/condition_variable_wait_timed.cc",
+    "//starboard/shared/pthread/mutex_acquire.cc",
+    "//starboard/shared/pthread/mutex_acquire_try.cc",
+    "//starboard/shared/pthread/mutex_create.cc",
+    "//starboard/shared/pthread/mutex_destroy.cc",
+    "//starboard/shared/pthread/mutex_release.cc",
+    "//starboard/shared/pthread/once.cc",
+    "//starboard/shared/pthread/thread_context_get_pointer.cc",
+    "//starboard/shared/pthread/thread_context_internal.cc",
+    "//starboard/shared/pthread/thread_context_internal.h",
+    "//starboard/shared/pthread/thread_create.cc",
+    "//starboard/shared/pthread/thread_create_local_key.cc",
+    "//starboard/shared/pthread/thread_create_priority.h",
+    "//starboard/shared/pthread/thread_destroy_local_key.cc",
+    "//starboard/shared/pthread/thread_detach.cc",
+    "//starboard/shared/pthread/thread_get_current.cc",
+    "//starboard/shared/pthread/thread_get_local_value.cc",
+    "//starboard/shared/pthread/thread_is_equal.cc",
+    "//starboard/shared/pthread/thread_join.cc",
+    "//starboard/shared/pthread/thread_sampler_create.cc",
+    "//starboard/shared/pthread/thread_sampler_destroy.cc",
+    "//starboard/shared/pthread/thread_sampler_freeze.cc",
+    "//starboard/shared/pthread/thread_sampler_internal.cc",
+    "//starboard/shared/pthread/thread_sampler_internal.h",
+    "//starboard/shared/pthread/thread_sampler_is_supported.cc",
+    "//starboard/shared/pthread/thread_sampler_thaw.cc",
+    "//starboard/shared/pthread/thread_set_local_value.cc",
+    "//starboard/shared/pthread/thread_yield.cc",
+    "//starboard/shared/signal/crash_signals.cc",
+    "//starboard/shared/signal/crash_signals.h",
+    "//starboard/shared/signal/suspend_signals.cc",
+    "//starboard/shared/signal/suspend_signals.h",
+    "//starboard/shared/signal/system_request_conceal.cc",
+    "//starboard/shared/signal/system_request_freeze.cc",
+    "//starboard/shared/signal/system_request_suspend.cc",
+    "//starboard/shared/starboard/application.cc",
+    "//starboard/shared/starboard/audio_sink/audio_sink_create.cc",
+    "//starboard/shared/starboard/audio_sink/audio_sink_destroy.cc",
+    "//starboard/shared/starboard/audio_sink/audio_sink_get_max_channels_5_1.cc",
+    "//starboard/shared/starboard/audio_sink/audio_sink_get_min_buffer_size_in_frames.cc",
+    "//starboard/shared/starboard/audio_sink/audio_sink_get_nearest_supported_sample_frequency.cc",
+    "//starboard/shared/starboard/audio_sink/audio_sink_internal.cc",
+    "//starboard/shared/starboard/audio_sink/audio_sink_internal.h",
+    "//starboard/shared/starboard/audio_sink/audio_sink_is_audio_frame_storage_type_supported_interleaved_only.cc",
+    "//starboard/shared/starboard/audio_sink/audio_sink_is_audio_sample_type_supported_float32_only.cc",
+    "//starboard/shared/starboard/audio_sink/audio_sink_is_valid.cc",
+    "//starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc",
+    "//starboard/shared/starboard/audio_sink/stub_audio_sink_type.h",
+    "//starboard/shared/starboard/command_line.cc",
+    "//starboard/shared/starboard/command_line.h",
+    "//starboard/shared/starboard/crash_handler.cc",
+    "//starboard/shared/starboard/crash_handler.h",
+    "//starboard/shared/starboard/directory_can_open.cc",
+    "//starboard/shared/starboard/event_cancel.cc",
+    "//starboard/shared/starboard/event_schedule.cc",
+    "//starboard/shared/starboard/file_atomic_replace_write_file.cc",
+    "//starboard/shared/starboard/file_atomic_replace_write_file.h",
+    "//starboard/shared/starboard/file_mode_string_to_flags.cc",
+    "//starboard/shared/starboard/file_storage/storage_close_record.cc",
+    "//starboard/shared/starboard/file_storage/storage_delete_record.cc",
+    "//starboard/shared/starboard/file_storage/storage_get_record_size.cc",
+    "//starboard/shared/starboard/file_storage/storage_open_record.cc",
+    "//starboard/shared/starboard/file_storage/storage_read_record.cc",
+    "//starboard/shared/starboard/log_mutex.cc",
+    "//starboard/shared/starboard/log_mutex.h",
+    "//starboard/shared/starboard/log_raw_dump_stack.cc",
+    "//starboard/shared/starboard/log_raw_format.cc",
+    "//starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc",
+    "//starboard/shared/starboard/media/media_get_audio_buffer_budget.cc",
+    "//starboard/shared/starboard/media/media_get_audio_configuration_5_1.cc",
+    "//starboard/shared/starboard/media/media_get_audio_output_count_single_audio_output.cc",
+    "//starboard/shared/starboard/media/media_get_buffer_alignment.cc",
+    "//starboard/shared/starboard/media/media_get_buffer_allocation_unit.cc",
+    "//starboard/shared/starboard/media/media_get_buffer_garbage_collection_duration_threshold.cc",
+    "//starboard/shared/starboard/media/media_get_buffer_padding.cc",
+    "//starboard/shared/starboard/media/media_get_buffer_storage_type.cc",
+    "//starboard/shared/starboard/media/media_get_initial_buffer_capacity.cc",
+    "//starboard/shared/starboard/media/media_get_max_buffer_capacity.cc",
+    "//starboard/shared/starboard/media/media_get_progressive_buffer_budget.cc",
+    "//starboard/shared/starboard/media/media_get_video_buffer_budget.cc",
+    "//starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc",
+    "//starboard/shared/starboard/media/media_is_buffer_pool_allocate_on_demand.cc",
+    "//starboard/shared/starboard/media/media_is_buffer_using_memory_pool.cc",
+    "//starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc",
+    "//starboard/shared/starboard/media/mime_type.cc",
+    "//starboard/shared/starboard/media/mime_type.h",
+    "//starboard/shared/starboard/memory.cc",
+    "//starboard/shared/starboard/new.cc",
+    "//starboard/shared/starboard/queue_application.cc",
+    "//starboard/shared/starboard/string_concat.cc",
+    "//starboard/shared/starboard/string_concat_wide.cc",
+    "//starboard/shared/starboard/string_copy.cc",
+    "//starboard/shared/starboard/string_copy_wide.cc",
+    "//starboard/shared/starboard/string_duplicate.cc",
+    "//starboard/shared/starboard/system_get_random_uint64.cc",
+    "//starboard/shared/starboard/system_request_blur.cc",
+    "//starboard/shared/starboard/system_request_focus.cc",
+    "//starboard/shared/starboard/system_request_pause.cc",
+    "//starboard/shared/starboard/system_request_reveal.cc",
+    "//starboard/shared/starboard/system_request_stop.cc",
+    "//starboard/shared/starboard/system_request_unpause.cc",
+    "//starboard/shared/starboard/system_supports_resume.cc",
+    "//starboard/shared/starboard/window_set_default_options.cc",
+    "//starboard/shared/stub/accessibility_get_caption_settings.cc",
+    "//starboard/shared/stub/accessibility_get_display_settings.cc",
+    "//starboard/shared/stub/accessibility_get_text_to_speech_settings.cc",
+    "//starboard/shared/stub/accessibility_set_captions_enabled.cc",
+    "//starboard/shared/stub/cryptography_create_transformer.cc",
+    "//starboard/shared/stub/cryptography_destroy_transformer.cc",
+    "//starboard/shared/stub/cryptography_get_tag.cc",
+    "//starboard/shared/stub/cryptography_set_authenticated_data.cc",
+    "//starboard/shared/stub/cryptography_set_initialization_vector.cc",
+    "//starboard/shared/stub/cryptography_transform.cc",
+    "//starboard/shared/stub/drm_close_session.cc",
+    "//starboard/shared/stub/drm_create_system.cc",
+    "//starboard/shared/stub/drm_destroy_system.cc",
+    "//starboard/shared/stub/drm_generate_session_update_request.cc",
+    "//starboard/shared/stub/drm_get_metrics.cc",
+    "//starboard/shared/stub/drm_is_server_certificate_updatable.cc",
+    "//starboard/shared/stub/drm_update_server_certificate.cc",
+    "//starboard/shared/stub/drm_update_session.cc",
+    "//starboard/shared/stub/media_is_supported.cc",
+    "//starboard/shared/stub/media_set_audio_write_duration.cc",
+    "//starboard/shared/stub/microphone_close.cc",
+    "//starboard/shared/stub/microphone_create.cc",
+    "//starboard/shared/stub/microphone_destroy.cc",
+    "//starboard/shared/stub/microphone_get_available.cc",
+    "//starboard/shared/stub/microphone_is_sample_rate_supported.cc",
+    "//starboard/shared/stub/microphone_open.cc",
+    "//starboard/shared/stub/microphone_read.cc",
+    "//starboard/shared/stub/speech_synthesis_cancel.cc",
+    "//starboard/shared/stub/speech_synthesis_is_supported.cc",
+    "//starboard/shared/stub/speech_synthesis_speak.cc",
+    "//starboard/shared/stub/system_get_total_gpu_memory.cc",
+    "//starboard/shared/stub/system_get_used_gpu_memory.cc",
+    "//starboard/shared/stub/system_hide_splash_screen.cc",
+    "//starboard/shared/stub/system_network_is_disconnected.cc",
+    "//starboard/shared/stub/system_raise_platform_error.cc",
+    "//starboard/shared/stub/system_sign_with_certification_secret_key.cc",
+    "//starboard/shared/stub/ui_nav_get_interface.cc",
+    "//starboard/shared/stub/window_blur_on_screen_keyboard.cc",
+    "//starboard/shared/stub/window_focus_on_screen_keyboard.cc",
+    "//starboard/shared/stub/window_get_diagonal_size_in_inches.cc",
+    "//starboard/shared/stub/window_get_on_screen_keyboard_bounding_rect.cc",
+    "//starboard/shared/stub/window_hide_on_screen_keyboard.cc",
+    "//starboard/shared/stub/window_is_on_screen_keyboard_shown.cc",
+    "//starboard/shared/stub/window_on_screen_keyboard_is_supported.cc",
+    "//starboard/shared/stub/window_on_screen_keyboard_suggestions_supported.cc",
+    "//starboard/shared/stub/window_set_on_screen_keyboard_keep_focus.cc",
+    "//starboard/shared/stub/window_show_on_screen_keyboard.cc",
+    "//starboard/shared/stub/window_update_on_screen_keyboard_suggestions.cc",
+  ]
+
+  sources += common_player_sources
+
+  configs += [ "//starboard/build/config:starboard_implementation" ]
+
+  public_deps = [
+    ":starboard_base_symbolize",
+    "//starboard:starboard_headers_only",
+    "//starboard/common/",
+    "//starboard/shared/ffmpeg:ffmpeg_linked",
+    "//starboard/shared/starboard/media:media_util",
+    "//starboard/shared/starboard/player/filter:filter_based_player_sources",
+  ]
+  if (sb_is_evergreen_compatible) {
+    public_deps += [ "//starboard/elf_loader:evergreen_config" ]
+  }
+  if (sb_is_evergreen_compatible && !sb_evergreen_compatible_enable_lite) {
+    public_deps += [ "//starboard/loader_app:pending_restart" ]
+  }
+
+  deps = [
+    "//third_party/libevent",
+    "//third_party/opus",
+  ]
+  if (sb_evergreen_compatible_use_libunwind) {
+    deps += [ "//third_party/llvm-project/libunwind:unwind_starboard" ]
+  }
+}
+
+static_library("starboard_base_symbolize") {
+  sources = [
+    "//base/third_party/symbolize/demangle.cc",
+    "//base/third_party/symbolize/symbolize.cc",
+  ]
+
+  public_deps = [ "//starboard/elf_loader:evergreen_info" ]
+}
diff --git a/src/starboard/raspi/shared/platform_configuration/BUILD.gn b/src/starboard/raspi/shared/platform_configuration/BUILD.gn
new file mode 100644
index 0000000..fbbab79
--- /dev/null
+++ b/src/starboard/raspi/shared/platform_configuration/BUILD.gn
@@ -0,0 +1,195 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+declare_args() {
+  raspi_home = getenv("RASPI_HOME")
+}
+
+config("compiler_flags") {
+  cflags = []
+  cflags_c = []
+  cflags_cc = []
+  defines = []
+  ldflags = []
+
+  defines += [
+    # By default, <EGL/eglplatform.h> pulls in some X11 headers that have some
+    # nasty macros (|Status|, for example) that conflict with Chromium base.
+    "MESA_EGL_NO_X11_HEADERS",
+
+    # Cobalt on Linux flag
+    "COBALT_LINUX",
+    "__STDC_FORMAT_MACROS",  # so that we get PRI*
+    "_GNU_SOURCE=1",
+  ]
+
+  if (is_debug) {
+    cflags += [ "-O0" ]
+    cflags_cc += [ "-frtti" ]
+  } else if (is_devel) {
+    cflags += [ "-O2" ]
+    cflags_cc += [ "-frtti" ]
+  } else {
+    cflags += [ "-Wno-unused-but-set-variable" ]
+    cflags_cc += [ "-fno-rtti" ]
+  }
+
+  ldflags += [
+    "--sysroot=$raspi_home/busterroot",
+
+    # This is a quirk of Raspbian, these are required to link any GL-related
+    # libraries.
+    "-L$raspi_home/busterroot/opt/vc/lib",
+    "-Wl,-rpath=$raspi_home/busterroot/opt/vc/lib",
+    "-L$raspi_home/busterroot/usr/lib/arm-linux-gnueabihf",
+    "-Wl,-rpath=$raspi_home/busterroot/usr/lib/arm-linux-gnueabihf",
+    "-L$raspi_home/busterroot/lib/arm-linux-gnueabihf",
+    "-Wl,-rpath=$raspi_home/busterroot/lib/arm-linux-gnueabihf",
+
+    # Cleanup unused sections
+    "-Wl,-gc-sections",
+    "-Wl,--unresolved-symbols=ignore-in-shared-libs",
+  ]
+
+  cflags += [
+    # Generated by Audio Renderer and Audio Sink implementations.
+    "-Wno-reorder",
+
+    # Generated by code in the raspi/shared/open_max.
+    "-Wno-sign-compare",
+
+    # Generated by many starboard implementation files.
+    "-Wno-unused-parameter",
+    "-Wno-unused-variable",
+  ]
+
+  cflags += [
+    # Force char to be signed.
+    "-fsigned-char",
+
+    # Disable strict aliasing.
+    "-fno-strict-aliasing",
+
+    # Allow Skia"s SkVx.h to convert between vectors of different element
+    # types or number of subparts.
+    "-flax-vector-conversions",
+
+    # To support large files
+    "-D_FILE_OFFSET_BITS=64",
+
+    # Suppress some warnings that will be hard to fix.
+    "-Wno-unused-local-typedefs",
+    "-Wno-unused-result",
+    "-Wno-unused-function",
+    "-Wno-deprecated-declarations",
+    "-Wno-missing-field-initializers",
+    "-Wno-extra",
+    "-Wno-comment",  # Talk to my lawyer.
+    "-Wno-narrowing",
+    "-Wno-unknown-pragmas",
+    "-Wno-type-limits",  # TODO: We should actually look into these.
+
+    # It"s OK not to use some input parameters. Note that the order
+    # matters: Wall implies Wunused-parameter and Wno-unused-parameter
+    # has no effect if specified before Wall.
+    "-Wno-unused-parameter",
+
+    # Specify the sysroot with all your include dependencies.
+    "--sysroot=$raspi_home/busterroot",
+
+    # This is a quirk of Raspbian, these are required to include any
+    # GL-related headers.
+    "-I$raspi_home/busterroot/opt/vc/include",
+    "-I$raspi_home/busterroot/opt/vc/include/interface/vcos/pthreads",
+    "-I$raspi_home/busterroot/opt/vc/include/interface/vmcs_host/linux",
+    "-I$raspi_home/busterroot/usr/include/arm-linux-gnueabihf",
+  ]
+
+  if (!cobalt_fastbuild && (is_debug || is_devel)) {
+    cflags += [ "-g" ]
+  }
+
+  cflags_c += [ "-std=c11" ]
+  cflags_cc += [
+    "-std=gnu++14",
+    "-Wno-literal-suffix",
+  ]
+
+  if (sb_pedantic_warnings) {
+    cflags += [
+      "-Wall",
+      "-Wextra",
+      "-Wunreachable-code",
+
+      # Raspi toolchain is based off an old version of gcc, which
+      # falsely flags some code.  That same code does not warn with gcc 6.3.
+      # This decision should be revisited after raspi toolchain is upgraded.
+      "-Wno-maybe-uninitialized",
+
+      #TODO: Renable -Werror after fixing all warnings.
+      #"-Werror",
+      "-Wno-expansion-to-defined",
+      "-Wno-implicit-fallthrough",
+    ]
+  } else {
+    cflags += [
+      # Do not warn for implicit type conversions that may change a value.
+      "-Wno-conversion",
+    ]
+  }
+}
+
+config("platform_configuration") {
+  libs = [
+    "asound",
+    "avcodec",
+    "avformat",
+    "avutil",
+    ":libpthread.so.0",
+    "pthread",
+    "rt",
+    "openmaxil",
+    "bcm_host",
+    "vcos",
+    "vchiq_arm",
+    "brcmGLESv2",
+    "brcmEGL",
+
+    # Static libs must be last, to avoid __dlopen linker errors
+    "EGL_static",
+    "GLESv2_static",
+  ]
+
+  configs = [ "//starboard/raspi/shared/platform_configuration:compiler_flags" ]
+}
+
+config("speed") {
+  cflags = [
+    "-O2",
+
+    # Compile symbols in separate sections
+    "-ffunction-sections",
+    "-fdata-sections",
+  ]
+}
+
+config("size") {
+  cflags = [
+    "-Os",
+
+    # Compile symbols in separate sections
+    "-ffunction-sections",
+    "-fdata-sections",
+  ]
+}
diff --git a/src/starboard/raspi/shared/platform_configuration/configuration.gni b/src/starboard/raspi/shared/platform_configuration/configuration.gni
new file mode 100644
index 0000000..c96fc14
--- /dev/null
+++ b/src/starboard/raspi/shared/platform_configuration/configuration.gni
@@ -0,0 +1,20 @@
+# Copyright 2021 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//starboard/build/config/base_configuration.gni")
+
+sb_pedantic_warnings = true
+sb_static_contents_output_data_dir = "$root_out_dir/content"
+
+sabi_path = "//starboard/sabi/arm/hardfp/sabi-v$sb_api_version.json"
diff --git a/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc
index dbb1d9e..5127ae4 100644
--- a/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc
@@ -362,8 +362,8 @@
     return test_params;
   }
 
-  vector<const char*> supported_files =
-      GetSupportedAudioTestFiles(kExcludeHeaac, 6);
+  vector<const char*> supported_files = GetSupportedAudioTestFiles(
+      kExcludeHeaac, 6, "audiopassthrough=\"false\"");
 
   // Generate test cases. For example, we have |supported_files| [A, B, C].
   // Add tests A->A, A->B, A->C, B->A, B->B, B->C, C->A, C->B and C->C.
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
index 74b8adf..00933f3 100644
--- a/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
@@ -635,7 +635,10 @@
 INSTANTIATE_TEST_CASE_P(
     AudioDecoderTests,
     AudioDecoderTest,
-    Combine(ValuesIn(GetSupportedAudioTestFiles(kIncludeHeaac, 6)), Bool()));
+    Combine(ValuesIn(GetSupportedAudioTestFiles(kIncludeHeaac,
+                                                6,
+                                                "audiopassthrough=\"false\"")),
+            Bool()));
 
 }  // namespace
 }  // namespace testing
diff --git a/src/third_party/inspector_protocol/crdtp/json_platform.cc b/src/third_party/inspector_protocol/crdtp/json_platform.cc
index 59c8deb..21e26ce 100644
--- a/src/third_party/inspector_protocol/crdtp/json_platform.cc
+++ b/src/third_party/inspector_protocol/crdtp/json_platform.cc
@@ -16,6 +16,9 @@
 namespace json {
 namespace platform {
 bool StrToD(const char* str, double* result) {
+#if SB_IS(EVERGREEN)
+#error "The std::locale::classic() is not supported for Evergreen. Please use base::StringToDouble()."
+#endif
   std::istringstream is(str);
   is.imbue(std::locale::classic());
   is >> *result;
@@ -23,6 +26,9 @@
 }
 
 std::string DToStr(double value) {
+#if SB_IS(EVERGREEN)
+#error "The std::locale::classic() is not supported for Evergreen. Please use base::NumberToString()."
+#endif
   std::stringstream ss;
   ss.imbue(std::locale::classic());
   ss << value;
diff --git a/src/third_party/libevent/evdns.c b/src/third_party/libevent/evdns.c
index 05fe594..d72fdaa 100644
--- a/src/third_party/libevent/evdns.c
+++ b/src/third_party/libevent/evdns.c
@@ -783,7 +783,6 @@
 
 	for(;;) {
 		u8 label_len;
-		if (j >= length) return -1;
 		GET8(label_len);
 		if (!label_len) break;
 		if (label_len & 0xc0) {
@@ -804,6 +803,7 @@
 			*cp++ = '.';
 		}
 		if (cp + label_len >= end) return -1;
+		if (j + label_len > length) return -1;
 		memcpy(cp, packet + j, label_len);
 		cp += label_len;
 		j += label_len;
diff --git a/src/third_party/libjpeg-turbo/BUILD.gn b/src/third_party/libjpeg-turbo/BUILD.gn
new file mode 100644
index 0000000..d566340
--- /dev/null
+++ b/src/third_party/libjpeg-turbo/BUILD.gn
@@ -0,0 +1,346 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Do not use the targets in this file unless you need a certain libjpeg
+# implementation. Use the meta target //third_party:jpeg instead.
+
+import("//build/config/sanitizers/sanitizers.gni")
+if (current_cpu == "arm" || current_cpu == "arm64") {
+  import("//build/config/arm.gni")
+}
+
+assert(!is_ios, "This is not used on iOS, don't drag it in unintentionally")
+
+source_set("libjpeg_headers") {
+  sources = [
+    "jconfig.h",
+    "jdct.h",
+    "jinclude.h",
+    "jmorecfg.h",
+    "jpeglib.h",
+    "jpeglibmangler.h",
+  ]
+  defines = [ "MANGLE_JPEG_NAMES" ]
+}
+
+if (current_cpu == "x86" || current_cpu == "x64") {
+  import("//third_party/nasm/nasm_assemble.gni")
+
+  nasm_assemble("simd_asm") {
+    defines = []
+    include_dirs = [ "simd/nasm/" ]
+
+    if (current_cpu == "x86") {
+      include_dirs += [ "simd/i386/" ]
+      sources = [
+        "simd/i386/jccolor-avx2.asm",
+        "simd/i386/jccolor-mmx.asm",
+        "simd/i386/jccolor-sse2.asm",
+        "simd/i386/jcgray-avx2.asm",
+        "simd/i386/jcgray-mmx.asm",
+        "simd/i386/jcgray-sse2.asm",
+        "simd/i386/jchuff-sse2.asm",
+        "simd/i386/jcphuff-sse2.asm",
+        "simd/i386/jcsample-avx2.asm",
+        "simd/i386/jcsample-mmx.asm",
+        "simd/i386/jcsample-sse2.asm",
+        "simd/i386/jdcolor-avx2.asm",
+        "simd/i386/jdcolor-mmx.asm",
+        "simd/i386/jdcolor-sse2.asm",
+        "simd/i386/jdmerge-avx2.asm",
+        "simd/i386/jdmerge-mmx.asm",
+        "simd/i386/jdmerge-sse2.asm",
+        "simd/i386/jdsample-avx2.asm",
+        "simd/i386/jdsample-mmx.asm",
+        "simd/i386/jdsample-sse2.asm",
+        "simd/i386/jfdctflt-3dn.asm",
+        "simd/i386/jfdctflt-sse.asm",
+        "simd/i386/jfdctfst-mmx.asm",
+        "simd/i386/jfdctfst-sse2.asm",
+        "simd/i386/jfdctint-avx2.asm",
+        "simd/i386/jfdctint-mmx.asm",
+        "simd/i386/jfdctint-sse2.asm",
+        "simd/i386/jidctflt-3dn.asm",
+        "simd/i386/jidctflt-sse.asm",
+        "simd/i386/jidctflt-sse2.asm",
+        "simd/i386/jidctfst-mmx.asm",
+        "simd/i386/jidctfst-sse2.asm",
+        "simd/i386/jidctint-avx2.asm",
+        "simd/i386/jidctint-mmx.asm",
+        "simd/i386/jidctint-sse2.asm",
+        "simd/i386/jidctred-mmx.asm",
+        "simd/i386/jidctred-sse2.asm",
+        "simd/i386/jquant-3dn.asm",
+        "simd/i386/jquant-mmx.asm",
+        "simd/i386/jquant-sse.asm",
+        "simd/i386/jquantf-sse2.asm",
+        "simd/i386/jquanti-avx2.asm",
+        "simd/i386/jquanti-sse2.asm",
+        "simd/i386/jsimdcpu.asm",
+      ]
+      defines += [
+        "__x86__",
+        "PIC",
+      ]
+    } else if (current_cpu == "x64") {
+      include_dirs += [ "simd/x86_64/" ]
+      sources = [
+        "simd/x86_64/jccolor-avx2.asm",
+        "simd/x86_64/jccolor-sse2.asm",
+        "simd/x86_64/jcgray-avx2.asm",
+        "simd/x86_64/jcgray-sse2.asm",
+        "simd/x86_64/jchuff-sse2.asm",
+        "simd/x86_64/jcphuff-sse2.asm",
+        "simd/x86_64/jcsample-avx2.asm",
+        "simd/x86_64/jcsample-sse2.asm",
+        "simd/x86_64/jdcolor-avx2.asm",
+        "simd/x86_64/jdcolor-sse2.asm",
+        "simd/x86_64/jdmerge-avx2.asm",
+        "simd/x86_64/jdmerge-sse2.asm",
+        "simd/x86_64/jdsample-avx2.asm",
+        "simd/x86_64/jdsample-sse2.asm",
+        "simd/x86_64/jfdctflt-sse.asm",
+        "simd/x86_64/jfdctfst-sse2.asm",
+        "simd/x86_64/jfdctint-avx2.asm",
+        "simd/x86_64/jfdctint-sse2.asm",
+        "simd/x86_64/jidctflt-sse2.asm",
+        "simd/x86_64/jidctfst-sse2.asm",
+        "simd/x86_64/jidctint-avx2.asm",
+        "simd/x86_64/jidctint-sse2.asm",
+        "simd/x86_64/jidctred-sse2.asm",
+        "simd/x86_64/jquantf-sse2.asm",
+        "simd/x86_64/jquanti-avx2.asm",
+        "simd/x86_64/jquanti-sse2.asm",
+        "simd/x86_64/jsimdcpu.asm",
+      ]
+      defines += [
+        "__x86_64__",
+        "PIC",
+      ]
+    }
+
+    if (is_win) {
+      defines += [ "MSVC" ]
+      if (current_cpu == "x86") {
+        defines += [ "WIN32" ]
+      } else {
+        defines += [ "WIN64" ]
+      }
+    } else if (is_mac || is_ios) {
+      defines += [ "MACHO" ]
+    } else if (is_linux || is_android || is_fuchsia || is_chromeos) {
+      defines += [ "ELF" ]
+    }
+  }
+}
+
+static_library("simd") {
+  include_dirs = [ "." ]
+  deps = [ ":libjpeg_headers" ]
+
+  if (current_cpu == "x86") {
+    deps += [ ":simd_asm" ]
+    sources = [ "simd/i386/jsimd.c" ]
+  } else if (current_cpu == "x64") {
+    deps += [ ":simd_asm" ]
+    sources = [ "simd/x86_64/jsimd.c" ]
+  } else if ((current_cpu == "arm" || current_cpu == "arm64") && arm_use_neon) {
+    include_dirs += [ "simd/arm/" ]
+
+    sources = [
+      "simd/arm/jccolor-neon.c",
+      "simd/arm/jcgray-neon.c",
+      "simd/arm/jcphuff-neon.c",
+      "simd/arm/jcsample-neon.c",
+      "simd/arm/jdcolor-neon.c",
+      "simd/arm/jdmerge-neon.c",
+      "simd/arm/jdsample-neon.c",
+      "simd/arm/jfdctfst-neon.c",
+      "simd/arm/jfdctint-neon.c",
+      "simd/arm/jidctfst-neon.c",
+      "simd/arm/jidctint-neon.c",
+      "simd/arm/jidctred-neon.c",
+      "simd/arm/jquanti-neon.c",
+    ]
+    if (current_cpu == "arm") {
+      sources += [
+        "simd/arm/aarch32/jchuff-neon.c",
+        "simd/arm/aarch32/jsimd.c",
+      ]
+    } else if (current_cpu == "arm64") {
+      sources += [
+        "simd/arm/aarch64/jchuff-neon.c",
+        "simd/arm/aarch64/jsimd.c",
+      ]
+    }
+
+    defines = [ "NEON_INTRINSICS" ]
+
+    configs -= [ "//build/config/compiler:default_optimization" ]
+    configs += [ "//build/config/compiler:optimize_speed" ]
+  } else {
+    sources = [ "jsimd_none.c" ]
+  }
+
+  if (is_win) {
+    cflags = [ "/wd4245" ]
+  }
+}
+
+config("libjpeg_config") {
+  include_dirs = [ "." ]
+}
+
+static_library("libjpeg") {
+  sources = [
+    "jcapimin.c",
+    "jcapistd.c",
+    "jccoefct.c",
+    "jccolor.c",
+    "jcdctmgr.c",
+    "jchuff.c",
+    "jcicc.c",
+    "jcinit.c",
+    "jcmainct.c",
+    "jcmarker.c",
+    "jcmaster.c",
+    "jcomapi.c",
+    "jcparam.c",
+    "jcphuff.c",
+    "jcprepct.c",
+    "jcsample.c",
+    "jctrans.c",
+    "jdapimin.c",
+    "jdapistd.c",
+    "jdatadst.c",
+    "jdatasrc.c",
+    "jdcoefct.c",
+    "jdcolor.c",
+    "jddctmgr.c",
+    "jdhuff.c",
+    "jdicc.c",
+    "jdinput.c",
+    "jdmainct.c",
+    "jdmarker.c",
+    "jdmaster.c",
+    "jdmerge.c",
+    "jdphuff.c",
+    "jdpostct.c",
+    "jdsample.c",
+    "jdtrans.c",
+    "jerror.c",
+    "jfdctflt.c",
+    "jfdctfst.c",
+    "jfdctint.c",
+    "jidctflt.c",
+    "jidctfst.c",
+    "jidctint.c",
+    "jidctred.c",
+    "jmemmgr.c",
+    "jmemnobs.c",
+    "jpeg_nbits_table.c",
+    "jquant1.c",
+    "jquant2.c",
+    "jutils.c",
+  ]
+
+  defines = [
+    "WITH_SIMD",
+    "NO_GETENV",
+  ]
+
+  configs += [ ":libjpeg_config" ]
+
+  public_configs = [ ":libjpeg_config" ]
+  public_deps = [ ":libjpeg_headers" ]
+
+  # MemorySanitizer doesn't support assembly code, so keep it disabled in x86
+  # and x64 MSan builds for now.
+  if (is_msan && (current_cpu == "x86" || current_cpu == "x64")) {
+    sources += [ "jsimd_none.c" ]
+  } else {
+    public_deps += [ ":simd" ]
+
+    if ((current_cpu == "arm" || current_cpu == "arm64") && arm_use_neon) {
+      defines += [ "NEON_INTRINSICS" ]
+    }
+  }
+}
+
+static_library("turbojpeg") {
+  sources = [
+    "jdatadst-tj.c",
+    "jdatasrc-tj.c",
+    "rdbmp.c",
+    "rdppm.c",
+    "transupp.c",
+    "turbojpeg.c",
+    "wrbmp.c",
+    "wrppm.c",
+  ]
+
+  defines = [
+    "WITH_SIMD",
+    "BMP_SUPPORTED",
+    "PPM_SUPPORTED",
+  ]
+
+  configs += [ ":libjpeg_config" ]
+
+  public_configs = [ ":libjpeg_config" ]
+  public_deps = [ ":libjpeg" ]
+}
+
+if (build_with_chromium) {
+  import("//testing/test.gni")
+
+  test("libjpeg_turbo_unittests") {
+    testonly = true
+
+    sources = [
+      "cdjpeg.c",
+      "cjpeg.c",
+      "djpeg.c",
+      "gtest/cjpeg-gtest-wrapper.cpp",
+      "gtest/djpeg-gtest-wrapper.cpp",
+      "gtest/gtest-utils.cpp",
+      "gtest/jpegtran-gtest-wrapper.cpp",
+      "gtest/tjbench-gtest-wrapper.cpp",
+      "gtest/tjunittest-gtest-wrapper.cpp",
+      "jpegtran.c",
+      "md5/md5.c",
+      "md5/md5hl.c",
+      "rdcolmap.c",
+      "rdgif.c",
+      "rdswitch.c",
+      "tjbench.c",
+      "tjunittest.c",
+      "tjutil.c",
+    ]
+
+    deps = [
+      ":turbojpeg",
+      "//base",
+      "//testing/gtest",
+      "//testing/gtest:gtest_main",
+    ]
+
+    data = [ "testimages/" ]
+
+    defines = [
+      "GTEST",
+      "WITH_SIMD",
+      "BMP_SUPPORTED",
+      "PPM_SUPPORTED",
+    ]
+
+    include_dirs = [
+      "//third_party/googletest/src/googletest/include/gtest",
+      ".",
+    ]
+
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+  }
+}
diff --git a/src/third_party/libjpeg-turbo/BUILDING.md b/src/third_party/libjpeg-turbo/BUILDING.md
index 429963e..f91abcd 100644
--- a/src/third_party/libjpeg-turbo/BUILDING.md
+++ b/src/third_party/libjpeg-turbo/BUILDING.md
@@ -12,16 +12,18 @@
 
 - [NASM](http://www.nasm.us) or [YASM](http://yasm.tortall.net)
   (if building x86 or x86-64 SIMD extensions)
-  * If using NASM, 2.10 or later is required.
-  * If using NASM, 2.10 or later (except 2.11.08) is required for an x86-64 Mac
-    build (2.11.08 does not work properly with libjpeg-turbo's x86-64 SIMD code
-    when building macho64 objects.)  NASM or YASM can be obtained from
-    [MacPorts](http://www.macports.org/) or [Homebrew](http://brew.sh/).
+  * If using NASM, 2.13 or later is required.
   * If using YASM, 1.2.0 or later is required.
+  * If building on macOS, NASM or YASM can be obtained from
+    [MacPorts](http://www.macports.org/) or [Homebrew](http://brew.sh/).
      - NOTE: Currently, if it is desirable to hide the SIMD function symbols in
        Mac executables or shared libraries that statically link with
-       libjpeg-turbo, then YASM must be used when building libjpeg-turbo.
+       libjpeg-turbo, then NASM 2.14 or later or YASM must be used when
+       building libjpeg-turbo.
   * If building on Windows, **nasm.exe**/**yasm.exe** should be in your `PATH`.
+  * NASM and YASM are located in the CRB (Code Ready Builder) repository on
+    Red Hat Enterprise Linux 8 and in the PowerTools repository on CentOS 8,
+    which is not enabled by default.
 
   The binary RPMs released by the NASM project do not work on older Linux
   systems, such as Red Hat Enterprise Linux 5.  On such systems, you can easily
@@ -44,34 +46,33 @@
 
 - If building the TurboJPEG Java wrapper, JDK or OpenJDK 1.5 or later is
   required.  Most modern Linux distributions, as well as Solaris 10 and later,
-  include JDK or OpenJDK.  On OS X 10.5 and 10.6, it will be necessary to
-  install the Java Developer Package, which can be downloaded from
-  <http://developer.apple.com/downloads> (Apple ID required.)  For other
-  systems, you can obtain the Oracle Java Development Kit from
-  <http://www.java.com>.
+  include JDK or OpenJDK.  For other systems, you can obtain the Oracle Java
+  Development Kit from
+  <http://www.oracle.com/technetwork/java/javase/downloads>.
 
+  * If using JDK 11 or later, CMake 3.10.x or later must also be used.
 
 ### Windows
 
 - Microsoft Visual C++ 2005 or later
 
   If you don't already have Visual C++, then the easiest way to get it is by
-  installing the
-  [Windows SDK](http://msdn.microsoft.com/en-us/windows/bb980924.aspx).
-  The Windows SDK includes both 32-bit and 64-bit Visual C++ compilers and
-  everything necessary to build libjpeg-turbo.
+  installing
+  [Visual Studio Community Edition](https://visualstudio.microsoft.com),
+  which includes everything necessary to build libjpeg-turbo.
 
-  * You can also use Microsoft Visual Studio Express/Community Edition, which
-    is a free download.  (NOTE: versions prior to 2012 can only be used to
-    build 32-bit code.)
+  * You can also download and install the standalone Windows SDK (for Windows 7
+    or later), which includes command-line versions of the 32-bit and 64-bit
+    Visual C++ compilers.
   * If you intend to build libjpeg-turbo from the command line, then add the
     appropriate compiler and SDK directories to the `INCLUDE`, `LIB`, and
     `PATH` environment variables.  This is generally accomplished by
-    executing `vcvars32.bat` or `vcvars64.bat` and `SetEnv.cmd`.
-    `vcvars32.bat` and `vcvars64.bat` are part of Visual C++ and are located in
-    the same directory as the compiler.  `SetEnv.cmd` is part of the Windows
-    SDK.  You can pass optional arguments to `SetEnv.cmd` to specify a 32-bit
-    or 64-bit build environment.
+    executing `vcvars32.bat` or `vcvars64.bat`, which are located in the same
+    directory as the compiler.
+  * If built with Visual C++ 2015 or later, the libjpeg-turbo static libraries
+    cannot be used with earlier versions of Visual C++, and vice versa.
+  * The libjpeg API DLL (**jpeg{version}.dll**) will depend on the C run-time
+    DLLs corresponding to the version of Visual C++ that was used to build it.
 
    ... OR ...
 
@@ -83,7 +84,10 @@
   appropriate compiler paths automatically set.
 
 - If building the TurboJPEG Java wrapper, JDK 1.5 or later is required.  This
-  can be downloaded from <http://www.java.com>.
+  can be downloaded from
+  <http://www.oracle.com/technetwork/java/javase/downloads>.
+
+  * If using JDK 11 or later, CMake 3.10.x or later must also be used.
 
 
 Out-of-Tree Builds
@@ -99,6 +103,13 @@
 directory.  For in-tree builds, these directories are the same.
 
 
+Ninja
+-----
+
+In all of the procedures and recipes below, replace `make` with `ninja` and
+`Unix Makefiles` with `Ninja` if using Ninja.
+
+
 Build Procedure
 ---------------
 
@@ -324,7 +335,7 @@
 -------------
 
 
-### 32-bit Build on 64-bit Linux/Unix/Mac
+### 32-bit Build on 64-bit Linux/Unix
 
 Use export/setenv to set the following environment variables before running
 CMake:
@@ -389,114 +400,25 @@
 Building libjpeg-turbo for iOS
 ------------------------------
 
-iOS platforms, such as the iPhone and iPad, use ARM processors, and all
-currently supported models include NEON instructions.  Thus, they can take
+iOS platforms, such as the iPhone and iPad, use Arm processors, and all
+currently supported models include Neon instructions.  Thus, they can take
 advantage of libjpeg-turbo's SIMD extensions to significantly accelerate JPEG
 compression/decompression.  This section describes how to build libjpeg-turbo
 for these platforms.
 
 
-### Additional build requirements
+### Armv8 (64-bit)
 
-- For configurations that require [gas-preprocessor.pl]
-  (https://raw.githubusercontent.com/libjpeg-turbo/gas-preprocessor/master/gas-preprocessor.pl),
-  it should be installed in your `PATH`.
-
-
-### ARMv7 (32-bit)
-
-**gas-preprocessor.pl required**
-
-The following scripts demonstrate how to build libjpeg-turbo to run on the
-iPhone 3GS-4S/iPad 1st-3rd Generation and newer:
-
-#### Xcode 4.2 and earlier (LLVM-GCC)
-
-    IOS_PLATFORMDIR=/Developer/Platforms/iPhoneOS.platform
-    IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk)
-    export CFLAGS="-mfloat-abi=softfp -march=armv7 -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -miphoneos-version-min=3.0"
-
-    cat <<EOF >toolchain.cmake
-    set(CMAKE_SYSTEM_NAME Darwin)
-    set(CMAKE_SYSTEM_PROCESSOR arm)
-    set(CMAKE_C_COMPILER ${IOS_PLATFORMDIR}/Developer/usr/bin/arm-apple-darwin10-llvm-gcc-4.2)
-    EOF
-
-    cd {build_directory}
-    cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-      -DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} \
-      [additional CMake flags] {source_directory}
-    make
-
-#### Xcode 4.3-4.6 (LLVM-GCC)
-
-Same as above, but replace the first line with:
-
-    IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
-
-#### Xcode 5 and later (Clang)
-
-    IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
-    IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk)
-    export CFLAGS="-mfloat-abi=softfp -arch armv7 -miphoneos-version-min=3.0"
-    export ASMFLAGS="-no-integrated-as"
-
-    cat <<EOF >toolchain.cmake
-    set(CMAKE_SYSTEM_NAME Darwin)
-    set(CMAKE_SYSTEM_PROCESSOR arm)
-    set(CMAKE_C_COMPILER /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
-    EOF
-
-    cd {build_directory}
-    cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-      -DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} \
-      [additional CMake flags] {source_directory}
-    make
-
-
-### ARMv7s (32-bit)
-
-**gas-preprocessor.pl required**
-
-The following scripts demonstrate how to build libjpeg-turbo to run on the
-iPhone 5/iPad 4th Generation and newer:
-
-#### Xcode 4.5-4.6 (LLVM-GCC)
-
-    IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
-    IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk)
-    export CFLAGS="-Wall -mfloat-abi=softfp -march=armv7s -mcpu=swift -mtune=swift -mfpu=neon -miphoneos-version-min=6.0"
-
-    cat <<EOF >toolchain.cmake
-    set(CMAKE_SYSTEM_NAME Darwin)
-    set(CMAKE_SYSTEM_PROCESSOR arm)
-    set(CMAKE_C_COMPILER ${IOS_PLATFORMDIR}/Developer/usr/bin/arm-apple-darwin10-llvm-gcc-4.2)
-    EOF
-
-    cd {build_directory}
-    cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-      -DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} \
-      [additional CMake flags] {source_directory}
-    make
-
-#### Xcode 5 and later (Clang)
-
-Same as the ARMv7 build procedure for Xcode 5 and later, except replace the
-compiler flags as follows:
-
-    export CFLAGS="-Wall -mfloat-abi=softfp -arch armv7s -miphoneos-version-min=6.0"
-
-
-### ARMv8 (64-bit)
-
-**gas-preprocessor.pl required if using Xcode < 6**
+**Xcode 5 or later required, Xcode 6.3.x or later recommended**
 
 The following script demonstrates how to build libjpeg-turbo to run on the
 iPhone 5S/iPad Mini 2/iPad Air and newer.
 
     IOS_PLATFORMDIR=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
     IOS_SYSROOT=($IOS_PLATFORMDIR/Developer/SDKs/iPhoneOS*.sdk)
-    export CFLAGS="-Wall -arch arm64 -miphoneos-version-min=7.0 -funwind-tables"
+    export CFLAGS="-Wall -arch arm64 -miphoneos-version-min=8.0 -funwind-tables"
+
+    cd {build_directory}
 
     cat <<EOF >toolchain.cmake
     set(CMAKE_SYSTEM_NAME Darwin)
@@ -504,94 +426,69 @@
     set(CMAKE_C_COMPILER /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang)
     EOF
 
-    cd {build_directory}
     cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
       -DCMAKE_OSX_SYSROOT=${IOS_SYSROOT[0]} \
       [additional CMake flags] {source_directory}
     make
 
-Once built, lipo can be used to combine the ARMv7, v7s, and/or v8 variants into
-a universal library.
-
 
 Building libjpeg-turbo for Android
 ----------------------------------
 
-Building libjpeg-turbo for Android platforms requires the
+Building libjpeg-turbo for Android platforms requires v13b or later of the
 [Android NDK](https://developer.android.com/tools/sdk/ndk).
 
 
-### ARMv7 (32-bit)
+### Armv7 (32-bit)
+
+**NDK r19 or later with Clang recommended**
 
 The following is a general recipe script that can be modified for your specific
 needs.
 
     # Set these variables to suit your needs
-    NDK_PATH={full path to the "ndk" directory-- for example, /opt/android/sdk/ndk-bundle}
-    BUILD_PLATFORM={the platform name for the NDK package you installed--
-      for example, "windows-x86" or "linux-x86_64" or "darwin-x86_64"}
-    TOOLCHAIN_VERSION={"4.8", "4.9", "clang3.5", etc.  This corresponds to a
-      toolchain directory under ${NDK_PATH}/toolchains/.}
-    ANDROID_VERSION={The minimum version of Android to support-- for example,
+    NDK_PATH={full path to the NDK directory-- for example,
+      /opt/android/android-ndk-r16b}
+    TOOLCHAIN={"gcc" or "clang"-- "gcc" must be used with NDK r16b and earlier,
+      and "clang" must be used with NDK r17c and later}
+    ANDROID_VERSION={the minimum version of Android to support-- for example,
       "16", "19", etc.}
 
-    # It should not be necessary to modify the rest
-    HOST=arm-linux-androideabi
-    SYSROOT=${NDK_PATH}/platforms/android-${ANDROID_VERSION}/arch-arm
-    export CFLAGS="-march=armv7-a -mfloat-abi=softfp -fprefetch-loop-arrays \
-      -D__ANDROID_API__=${ANDROID_VERSION} --sysroot=${SYSROOT} \
-      -isystem ${NDK_PATH}/sysroot/usr/include \
-      -isystem ${NDK_PATH}/sysroot/usr/include/${HOST}"
-    export LDFLAGS=-pie
-    TOOLCHAIN=${NDK_PATH}/toolchains/${HOST}-${TOOLCHAIN_VERSION}/prebuilt/${BUILD_PLATFORM}
-
-    cat <<EOF >toolchain.cmake
-    set(CMAKE_SYSTEM_NAME Linux)
-    set(CMAKE_SYSTEM_PROCESSOR arm)
-    set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${HOST}-gcc)
-    set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN}/${HOST})
-    EOF
-
     cd {build_directory}
-    cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-      -DCMAKE_POSITION_INDEPENDENT_CODE=1 \
+    cmake -G"Unix Makefiles" \
+      -DANDROID_ABI=armeabi-v7a \
+      -DANDROID_ARM_MODE=arm \
+      -DANDROID_PLATFORM=android-${ANDROID_VERSION} \
+      -DANDROID_TOOLCHAIN=${TOOLCHAIN} \
+      -DCMAKE_ASM_FLAGS="--target=arm-linux-androideabi${ANDROID_VERSION}" \
+      -DCMAKE_TOOLCHAIN_FILE=${NDK_PATH}/build/cmake/android.toolchain.cmake \
       [additional CMake flags] {source_directory}
     make
 
 
-### ARMv8 (64-bit)
+### Armv8 (64-bit)
+
+**Clang recommended**
 
 The following is a general recipe script that can be modified for your specific
 needs.
 
     # Set these variables to suit your needs
-    NDK_PATH={full path to the "ndk" directory-- for example, /opt/android/sdk/ndk-bundle}
-    BUILD_PLATFORM={the platform name for the NDK package you installed--
-      for example, "windows-x86" or "linux-x86_64" or "darwin-x86_64"}
-    TOOLCHAIN_VERSION={"4.8", "4.9", "clang3.5", etc.  This corresponds to a
-      toolchain directory under ${NDK_PATH}/toolchains/.}
-    ANDROID_VERSION={The minimum version of Android to support.  "21" or later
+    NDK_PATH={full path to the NDK directory-- for example,
+      /opt/android/android-ndk-r16b}
+    TOOLCHAIN={"gcc" or "clang"-- "gcc" must be used with NDK r14b and earlier,
+      and "clang" must be used with NDK r17c and later}
+    ANDROID_VERSION={the minimum version of Android to support.  "21" or later
       is required for a 64-bit build.}
 
-    # It should not be necessary to modify the rest
-    HOST=aarch64-linux-android
-    SYSROOT=${NDK_PATH}/platforms/android-${ANDROID_VERSION}/arch-arm64
-    export CFLAGS="-D__ANDROID_API__=${ANDROID_VERSION} --sysroot=${SYSROOT} \
-      -isystem ${NDK_PATH}/sysroot/usr/include \
-      -isystem ${NDK_PATH}/sysroot/usr/include/${HOST}"
-    export LDFLAGS=-pie
-    TOOLCHAIN=${NDK_PATH}/toolchains/${HOST}-${TOOLCHAIN_VERSION}/prebuilt/${BUILD_PLATFORM}
-
-    cat <<EOF >toolchain.cmake
-    set(CMAKE_SYSTEM_NAME Linux)
-    set(CMAKE_SYSTEM_PROCESSOR aarch64)
-    set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${HOST}-gcc)
-    set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN}/${HOST})
-    EOF
-
     cd {build_directory}
-    cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-      -DCMAKE_POSITION_INDEPENDENT_CODE=1 \
+    cmake -G"Unix Makefiles" \
+      -DANDROID_ABI=arm64-v8a \
+      -DANDROID_ARM_MODE=arm \
+      -DANDROID_PLATFORM=android-${ANDROID_VERSION} \
+      -DANDROID_TOOLCHAIN=${TOOLCHAIN} \
+      -DCMAKE_ASM_FLAGS="--target=aarch64-linux-android${ANDROID_VERSION}" \
+      -DCMAKE_TOOLCHAIN_FILE=${NDK_PATH}/build/cmake/android.toolchain.cmake \
       [additional CMake flags] {source_directory}
     make
 
@@ -602,33 +499,19 @@
 needs.
 
     # Set these variables to suit your needs
-    NDK_PATH={full path to the "ndk" directory-- for example, /opt/android/sdk/ndk-bundle}
-    BUILD_PLATFORM={the platform name for the NDK package you installed--
-      for example, "windows-x86" or "linux-x86_64" or "darwin-x86_64"}
-    TOOLCHAIN_VERSION={"4.8", "4.9", "clang3.5", etc.  This corresponds to a
-      toolchain directory under ${NDK_PATH}/toolchains/.}
+    NDK_PATH={full path to the NDK directory-- for example,
+      /opt/android/android-ndk-r16b}
+    TOOLCHAIN={"gcc" or "clang"-- "gcc" must be used with NDK r14b and earlier,
+      and "clang" must be used with NDK r17c and later}
     ANDROID_VERSION={The minimum version of Android to support-- for example,
       "16", "19", etc.}
 
-    # It should not be necessary to modify the rest
-    HOST=i686-linux-android
-    SYSROOT=${NDK_PATH}/platforms/android-${ANDROID_VERSION}/arch-x86
-    export CFLAGS="-D__ANDROID_API__=${ANDROID_VERSION} --sysroot=${SYSROOT} \
-      -isystem ${NDK_PATH}/sysroot/usr/include \
-      -isystem ${NDK_PATH}/sysroot/usr/include/${HOST}"
-    export LDFLAGS=-pie
-    TOOLCHAIN=${NDK_PATH}/toolchains/x86-${TOOLCHAIN_VERSION}/prebuilt/${BUILD_PLATFORM}
-
-    cat <<EOF >toolchain.cmake
-    set(CMAKE_SYSTEM_NAME Linux)
-    set(CMAKE_SYSTEM_PROCESSOR i386)
-    set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${HOST}-gcc)
-    set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN}/${HOST})
-    EOF
-
     cd {build_directory}
-    cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-      -DCMAKE_POSITION_INDEPENDENT_CODE=1 \
+    cmake -G"Unix Makefiles" \
+      -DANDROID_ABI=x86 \
+      -DANDROID_PLATFORM=android-${ANDROID_VERSION} \
+      -DANDROID_TOOLCHAIN=${TOOLCHAIN} \
+      -DCMAKE_TOOLCHAIN_FILE=${NDK_PATH}/build/cmake/android.toolchain.cmake \
       [additional CMake flags] {source_directory}
     make
 
@@ -639,42 +522,23 @@
 needs.
 
     # Set these variables to suit your needs
-    NDK_PATH={full path to the "ndk" directory-- for example, /opt/android/sdk/ndk-bundle}
-    BUILD_PLATFORM={the platform name for the NDK package you installed--
-      for example, "windows-x86" or "linux-x86_64" or "darwin-x86_64"}
-    TOOLCHAIN_VERSION={"4.8", "4.9", "clang3.5", etc.  This corresponds to a
-      toolchain directory under ${NDK_PATH}/toolchains/.}
-    ANDROID_VERSION={The minimum version of Android to support.  "21" or later
+    NDK_PATH={full path to the NDK directory-- for example,
+      /opt/android/android-ndk-r16b}
+    TOOLCHAIN={"gcc" or "clang"-- "gcc" must be used with NDK r14b and earlier,
+      and "clang" must be used with NDK r17c and later}
+    ANDROID_VERSION={the minimum version of Android to support.  "21" or later
       is required for a 64-bit build.}
 
-    # It should not be necessary to modify the rest
-    HOST=x86_64-linux-android
-    SYSROOT=${NDK_PATH}/platforms/android-${ANDROID_VERSION}/arch-x86_64
-    export CFLAGS="-D__ANDROID_API__=${ANDROID_VERSION} --sysroot=${SYSROOT} \
-      -isystem ${NDK_PATH}/sysroot/usr/include \
-      -isystem ${NDK_PATH}/sysroot/usr/include/${HOST}"
-    export LDFLAGS=-pie
-    TOOLCHAIN=${NDK_PATH}/toolchains/x86_64-${TOOLCHAIN_VERSION}/prebuilt/${BUILD_PLATFORM}
-
-    cat <<EOF >toolchain.cmake
-    set(CMAKE_SYSTEM_NAME Linux)
-    set(CMAKE_SYSTEM_PROCESSOR x86_64)
-    set(CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${HOST}-gcc)
-    set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN}/${HOST})
-    EOF
-
     cd {build_directory}
-    cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake \
-      -DCMAKE_POSITION_INDEPENDENT_CODE=1 \
+    cmake -G"Unix Makefiles" \
+      -DANDROID_ABI=x86_64 \
+      -DANDROID_PLATFORM=android-${ANDROID_VERSION} \
+      -DANDROID_TOOLCHAIN=${TOOLCHAIN} \
+      -DCMAKE_TOOLCHAIN_FILE=${NDK_PATH}/build/cmake/android.toolchain.cmake \
       [additional CMake flags] {source_directory}
     make
 
 
-If building for Android 4.0.x (API level < 16) or earlier, remove
-`-DCMAKE_POSITION_INDEPENDENT_CODE=1` from the CMake arguments and `-pie` from
-`LDFLAGS`.
-
-
 Advanced CMake Options
 ----------------------
 
@@ -780,44 +644,23 @@
     make dmg
 
 Create Mac package/disk image.  This requires pkgbuild and productbuild, which
-are installed by default on OS X 10.7 and later and which can be obtained by
-installing Xcode 3.2.6 (with the "Unix Development" option) on OS X 10.6.
-Packages built in this manner can be installed on OS X 10.5 and later, but they
-must be built on OS X 10.6 or later.
+are installed by default on OS X/macOS 10.7 and later.
 
-    make udmg
+In order to create a Mac package/disk image that contains universal
+x86-64/Arm binaries, set the following CMake variable:
 
-This creates a Mac package/disk image that contains universal x86-64/i386/ARM
-binaries.  The following CMake variables control which architectures are
-included in the universal binaries.  Setting any of these variables to an empty
-string excludes that architecture from the package.
+* `ARMV8_BUILD`: Directory containing an Armv8 (64-bit) iOS or macOS build of
+  libjpeg-turbo to include in the universal binaries
 
-* `OSX_32BIT_BUILD`: Directory containing an i386 (32-bit) Mac build of
-  libjpeg-turbo (default: *{source_directory}*/osxx86)
-* `IOS_ARMV7_BUILD`: Directory containing an ARMv7 (32-bit) iOS build of
-  libjpeg-turbo (default: *{source_directory}*/iosarmv7)
-* `IOS_ARMV7S_BUILD`: Directory containing an ARMv7s (32-bit) iOS build of
-  libjpeg-turbo (default: *{source_directory}*/iosarmv7s)
-* `IOS_ARMV8_BUILD`: Directory containing an ARMv8 (64-bit) iOS build of
-  libjpeg-turbo (default: *{source_directory}*/iosarmv8)
-
-You should first use CMake to configure i386, ARMv7, ARMv7s, and/or ARMv8
-sub-builds of libjpeg-turbo (see "Build Recipes" and "Building libjpeg-turbo
-for iOS" above) in build directories that match those specified in the
-aforementioned CMake variables.  Next, configure the primary build of
-libjpeg-turbo as an out-of-tree build, and build it.  Once the primary build
-has been built, run `make udmg` from the build directory.  The packaging system
-will build the sub-builds, use lipo to combine them into a single set of
-universal binaries, then package the universal binaries in the same manner as
-`make dmg`.
-
-
-Cygwin
-------
-
-    make cygwinpkg
-
-Build a Cygwin binary package.
+You should first use CMake to configure an Armv8 sub-build of libjpeg-turbo
+(see "Building libjpeg-turbo for iOS" above, if applicable) in a build
+directory that matches the one specified in the aforementioned CMake variable.
+Next, configure the primary (x86-64) build of libjpeg-turbo as an out-of-tree
+build, specifying the aforementioned CMake variable, and build it.  Once the
+primary build has been built, run `make dmg` from the build directory.  The
+packaging system will build the sub-build, use lipo to combine it with the
+primary build into a single set of universal binaries, then package the
+universal binaries.
 
 
 Windows
diff --git a/src/third_party/libjpeg-turbo/Brewfile b/src/third_party/libjpeg-turbo/Brewfile
deleted file mode 100644
index 4a9cb3d..0000000
--- a/src/third_party/libjpeg-turbo/Brewfile
+++ /dev/null
@@ -1,4 +0,0 @@
-brew 'yasm'
-brew 'gcc@5'
-brew 'md5sha1sum'
-cask 'Caskroom/versions/java6'
diff --git a/src/third_party/libjpeg-turbo/CMakeLists.txt b/src/third_party/libjpeg-turbo/CMakeLists.txt
deleted file mode 100644
index bea98b6..0000000
--- a/src/third_party/libjpeg-turbo/CMakeLists.txt
+++ /dev/null
@@ -1,1383 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-
-project(libjpeg-turbo C)
-set(VERSION 1.5.91)
-string(REPLACE "." ";" VERSION_TRIPLET ${VERSION})
-list(GET VERSION_TRIPLET 0 VERSION_MAJOR)
-list(GET VERSION_TRIPLET 1 VERSION_MINOR)
-list(GET VERSION_TRIPLET 2 VERSION_REVISION)
-function(pad_number NUMBER OUTPUT_LEN)
-  string(LENGTH "${${NUMBER}}" INPUT_LEN)
-  if(INPUT_LEN LESS OUTPUT_LEN)
-    math(EXPR ZEROES "${OUTPUT_LEN} - ${INPUT_LEN} - 1")
-    set(NUM ${${NUMBER}})
-    foreach(C RANGE ${ZEROES})
-      set(NUM "0${NUM}")
-    endforeach()
-    set(${NUMBER} ${NUM} PARENT_SCOPE)
-  endif()
-endfunction()
-pad_number(VERSION_MINOR 3)
-pad_number(VERSION_REVISION 3)
-set(LIBJPEG_TURBO_VERSION_NUMBER ${VERSION_MAJOR}${VERSION_MINOR}${VERSION_REVISION})
-
-string(TIMESTAMP DEFAULT_BUILD "%Y%m%d")
-set(BUILD ${DEFAULT_BUILD} CACHE STRING "Build string (default: ${DEFAULT_BUILD})")
-
-# NOTE: On Windows, this does nothing except when using MinGW or Cygwin.
-# CMAKE_BUILD_TYPE has no meaning in Visual Studio, and it always defaults to
-# Debug when using NMake.
-if(NOT CMAKE_BUILD_TYPE)
-  set(CMAKE_BUILD_TYPE Release)
-endif()
-message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
-
-message(STATUS "VERSION = ${VERSION}, BUILD = ${BUILD}")
-
-# Detect CPU type and whether we're building 64-bit or 32-bit code
-math(EXPR BITS "${CMAKE_SIZEOF_VOID_P} * 8")
-string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} CMAKE_SYSTEM_PROCESSOR_LC)
-if(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86_64" OR
-  CMAKE_SYSTEM_PROCESSOR_LC MATCHES "amd64" OR
-  CMAKE_SYSTEM_PROCESSOR_LC MATCHES "i[0-9]86" OR
-  CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86" OR
-  CMAKE_SYSTEM_PROCESSOR_LC MATCHES "ia32")
-  if(BITS EQUAL 64)
-    set(CPU_TYPE x86_64)
-  else()
-    set(CPU_TYPE i386)
-  endif()
-  if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL ${CPU_TYPE})
-    set(CMAKE_SYSTEM_PROCESSOR ${CPU_TYPE})
-  endif()
-elseif(CMAKE_SYSTEM_PROCESSOR_LC STREQUAL "aarch64" OR
-  CMAKE_SYSTEM_PROCESSOR_LC MATCHES "arm*64*")
-  set(CPU_TYPE arm64)
-elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "arm*")
-  set(CPU_TYPE arm)
-elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "ppc*" OR
-  CMAKE_SYSTEM_PROCESSOR_LC MATCHES "powerpc*")
-  set(CPU_TYPE powerpc)
-else()
-  set(CPU_TYPE ${CMAKE_SYSTEM_PROCESSOR_LC})
-endif()
-message(STATUS "${BITS}-bit build (${CPU_TYPE})")
-
-
-###############################################################################
-# INSTALL DIRECTORIES
-###############################################################################
-
-if(WIN32)
-  if(MSVC)
-    set(CMAKE_INSTALL_DEFAULT_PREFIX "c:/${CMAKE_PROJECT_NAME}")
-  else()
-    set(CMAKE_INSTALL_DEFAULT_PREFIX "c:/${CMAKE_PROJECT_NAME}-gcc")
-  endif()
-  if(BITS EQUAL 64)
-    set(CMAKE_INSTALL_DEFAULT_PREFIX "${CMAKE_INSTALL_DEFAULT_PREFIX}64")
-  endif()
-else()
-  set(CMAKE_INSTALL_DEFAULT_PREFIX /opt/${CMAKE_PROJECT_NAME})
-endif()
-if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
-  set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_DEFAULT_PREFIX}" CACHE PATH
-    "Directory into which to install ${CMAKE_PROJECT_NAME} (default: ${CMAKE_INSTALL_DEFAULT_PREFIX})"
-    FORCE)
-endif()
-message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
-
-# When the prefix is /opt/${CMAKE_PROJECT_NAME}, we assume that an "official"
-# build is being created, and thus we install things into specific locations.
-
-if(CMAKE_INSTALL_PREFIX STREQUAL "${CMAKE_INSTALL_DEFAULT_PREFIX}")
-  set(CMAKE_INSTALL_DEFAULT_DATAROOTDIR "")
-  set(CMAKE_INSTALL_DEFAULT_DOCDIR "<CMAKE_INSTALL_DATAROOTDIR>/doc")
-  set(CMAKE_INSTALL_DEFAULT_JAVADIR "<CMAKE_INSTALL_DATAROOTDIR>/classes")
-  if(UNIX AND NOT APPLE)
-    if(BITS EQUAL 64)
-      set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib64")
-    else()
-      set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib32")
-    endif()
-  endif()
-endif()
-
-include(cmakescripts/GNUInstallDirs.cmake)
-
-set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR})
-
-macro(report_directory var)
-  if(CMAKE_INSTALL_${var} STREQUAL CMAKE_INSTALL_FULL_${var})
-    message(STATUS "CMAKE_INSTALL_${var} = ${CMAKE_INSTALL_${var}}")
-  else()
-    message(STATUS "CMAKE_INSTALL_${var} = ${CMAKE_INSTALL_${var}} (${CMAKE_INSTALL_FULL_${var}})")
-  endif()
-  mark_as_advanced(CLEAR CMAKE_INSTALL_${var})
-endmacro()
-
-set(DIRLIST "BINDIR;DATAROOTDIR;DOCDIR;INCLUDEDIR;LIBDIR")
-if(UNIX)
-  list(APPEND DIRLIST "MANDIR")
-endif()
-foreach(dir ${DIRLIST})
-  report_directory(${dir})
-endforeach()
-
-
-###############################################################################
-# CONFIGURATION OPTIONS
-###############################################################################
-
-macro(boolean_number var)
-  if(${var})
-    set(${var} 1)
-  else()
-    set(${var} 0)
-  endif()
-endmacro()
-
-option(ENABLE_SHARED "Build shared libraries" TRUE)
-boolean_number(ENABLE_SHARED)
-option(ENABLE_STATIC "Build static libraries" TRUE)
-boolean_number(ENABLE_STATIC)
-option(REQUIRE_SIMD "Generate a fatal error if SIMD extensions are not available for this platform (default is to fall back to a non-SIMD build)" FALSE)
-boolean_number(REQUIRE_SIMD)
-option(WITH_12BIT "Encode/decode JPEG images with 12-bit samples (implies WITH_ARITH_DEC=0 WITH_ARITH_ENC=0 WITH_JAVA=0 WITH_SIMD=0 WITH_TURBOJPEG=0 )" FALSE)
-boolean_number(WITH_12BIT)
-option(WITH_ARITH_DEC "Include arithmetic decoding support when emulating the libjpeg v6b API/ABI" TRUE)
-boolean_number(WITH_ARITH_DEC)
-option(WITH_ARITH_ENC "Include arithmetic encoding support when emulating the libjpeg v6b API/ABI" TRUE)
-boolean_number(WITH_ARITH_ENC)
-option(WITH_JAVA "Build Java wrapper for the TurboJPEG API library (implies ENABLE_SHARED=1)" FALSE)
-boolean_number(WITH_JAVA)
-option(WITH_JPEG7 "Emulate libjpeg v7 API/ABI (this makes ${CMAKE_PROJECT_NAME} backward-incompatible with libjpeg v6b)" FALSE)
-boolean_number(WITH_JPEG7)
-option(WITH_JPEG8 "Emulate libjpeg v8 API/ABI (this makes ${CMAKE_PROJECT_NAME} backward-incompatible with libjpeg v6b)" FALSE)
-boolean_number(WITH_JPEG8)
-option(WITH_MEM_SRCDST "Include in-memory source/destination manager functions when emulating the libjpeg v6b or v7 API/ABI" TRUE)
-boolean_number(WITH_MEM_SRCDST)
-option(WITH_SIMD "Include SIMD extensions, if available for this platform" TRUE)
-boolean_number(WITH_SIMD)
-option(WITH_TURBOJPEG "Include the TurboJPEG API library and associated test programs" TRUE)
-boolean_number(WITH_TURBOJPEG)
-
-macro(report_option var desc)
-  if(${var})
-    message(STATUS "${desc} enabled (${var} = ${${var}})")
-  else()
-    message(STATUS "${desc} disabled (${var} = ${${var}})")
-  endif()
-endmacro()
-
-if(WITH_JAVA)
-  set(ENABLE_SHARED 1)
-endif()
-
-# Explicitly setting CMAKE_POSITION_INDEPENDENT_CODE=FALSE disables PIC for all
-# targets, which will cause the shared library builds to fail.  Thus, if shared
-# libraries are enabled and CMAKE_POSITION_INDEPENDENT_CODE is explicitly set
-# to FALSE, we need to unset it, thus restoring the default behavior
-# (automatically using PIC for shared library targets.)
-if(DEFINED CMAKE_POSITION_INDEPENDENT_CODE AND
-  NOT CMAKE_POSITION_INDEPENDENT_CODE AND ENABLE_SHARED)
-  unset(CMAKE_POSITION_INDEPENDENT_CODE CACHE)
-endif()
-
-report_option(ENABLE_SHARED "Shared libraries")
-report_option(ENABLE_STATIC "Static libraries")
-
-if(WITH_12BIT)
-  set(WITH_ARITH_DEC 0)
-  set(WITH_ARITH_ENC 0)
-  set(WITH_JAVA 0)
-  set(WITH_SIMD 0)
-  set(WITH_TURBOJPEG 0)
-  set(BITS_IN_JSAMPLE 12)
-else()
-  set(BITS_IN_JSAMPLE 8)
-endif()
-report_option(WITH_12BIT "12-bit JPEG support")
-
-if(WITH_JPEG8 OR WITH_JPEG7)
-  set(WITH_ARITH_ENC 1)
-  set(WITH_ARITH_DEC 1)
-endif()
-if(WITH_JPEG8)
-  set(WITH_MEM_SRCDST 0)
-endif()
-
-if(WITH_ARITH_DEC)
-  set(D_ARITH_CODING_SUPPORTED 1)
-endif()
-if(NOT WITH_12BIT)
-  report_option(WITH_ARITH_DEC "Arithmetic decoding support")
-endif()
-
-if(WITH_ARITH_ENC)
-  set(C_ARITH_CODING_SUPPORTED 1)
-endif()
-if(NOT WITH_12BIT)
-  report_option(WITH_ARITH_ENC "Arithmetic encoding support")
-endif()
-
-if(NOT WITH_12BIT)
-  report_option(WITH_TURBOJPEG "TurboJPEG API library")
-  report_option(WITH_JAVA "TurboJPEG Java wrapper")
-endif()
-
-if(WITH_MEM_SRCDST)
-  set(MEM_SRCDST_SUPPORTED 1)
-  set(MEM_SRCDST_FUNCTIONS "global:  jpeg_mem_dest;  jpeg_mem_src;")
-endif()
-if(NOT WITH_JPEG8)
-  report_option(WITH_MEM_SRCDST "In-memory source/destination managers")
-endif()
-
-set(SO_AGE 2)
-if(WITH_MEM_SRCDST)
-  set(SO_AGE 3)
-endif()
-
-if(WITH_JPEG8)
-  set(JPEG_LIB_VERSION 80)
-elseif(WITH_JPEG7)
-  set(JPEG_LIB_VERSION 70)
-else()
-  set(JPEG_LIB_VERSION 62)
-endif()
-
-math(EXPR JPEG_LIB_VERSION_DIV10 "${JPEG_LIB_VERSION} / 10")
-math(EXPR JPEG_LIB_VERSION_MOD10 "${JPEG_LIB_VERSION} % 10")
-if(JPEG_LIB_VERSION STREQUAL "62")
-  set(DEFAULT_SO_MAJOR_VERSION ${JPEG_LIB_VERSION})
-else()
-  set(DEFAULT_SO_MAJOR_VERSION ${JPEG_LIB_VERSION_DIV10})
-endif()
-if(JPEG_LIB_VERSION STREQUAL "80")
-  set(DEFAULT_SO_MINOR_VERSION 2)
-else()
-  set(DEFAULT_SO_MINOR_VERSION 0)
-endif()
-
-# This causes SO_MAJOR_VERSION/SO_MINOR_VERSION to reset to defaults if
-# WITH_JPEG7 or WITH_JPEG8 has changed.
-if((DEFINED WITH_JPEG7_INT AND NOT WITH_JPEG7 EQUAL WITH_JPEG7_INT) OR
-  (DEFINED WITH_JPEG8_INT AND NOT WITH_JPEG8 EQUAL WITH_JPEG8_INT))
-  set(FORCE_SO_VERSION "FORCE")
-endif()
-set(WITH_JPEG7_INT ${WITH_JPEG7} CACHE INTERNAL "")
-set(WITH_JPEG8_INT ${WITH_JPEG8} CACHE INTERNAL "")
-
-set(SO_MAJOR_VERSION ${DEFAULT_SO_MAJOR_VERSION} CACHE STRING
-  "Major version of the libjpeg API shared library (default: ${DEFAULT_SO_MAJOR_VERSION})"
-  ${FORCE_SO_VERSION})
-set(SO_MINOR_VERSION ${DEFAULT_SO_MINOR_VERSION} CACHE STRING
-  "Minor version of the libjpeg API shared library (default: ${DEFAULT_SO_MINOR_VERSION})"
-  ${FORCE_SO_VERSION})
-
-set(JPEG_LIB_VERSION_DECIMAL "${JPEG_LIB_VERSION_DIV10}.${JPEG_LIB_VERSION_MOD10}")
-message(STATUS "Emulating libjpeg API/ABI v${JPEG_LIB_VERSION_DECIMAL} (WITH_JPEG7 = ${WITH_JPEG7}, WITH_JPEG8 = ${WITH_JPEG8})")
-message(STATUS "libjpeg API shared library version = ${SO_MAJOR_VERSION}.${SO_AGE}.${SO_MINOR_VERSION}")
-
-# Because the TurboJPEG API library uses versioned symbols and changes the
-# names of functions whenever they are modified in a backward-incompatible
-# manner, it is always backward-ABI-compatible with itself, so the major and
-# minor SO versions don't change.  However, we increase the middle number (the
-# SO "age") whenever functions are added to the API.
-set(TURBOJPEG_SO_MAJOR_VERSION 0)
-set(TURBOJPEG_SO_VERSION 0.2.0)
-
-
-###############################################################################
-# COMPILER SETTINGS
-###############################################################################
-
-if(MSVC)
-  option(WITH_CRT_DLL
-    "Link all ${CMAKE_PROJECT_NAME} libraries and executables with the C run-time DLL (msvcr*.dll) instead of the static C run-time library (libcmt*.lib.)  The default is to use the C run-time DLL only with the libraries and executables that need it."
-    FALSE)
-  if(NOT WITH_CRT_DLL)
-    # Use the static C library for all build types
-    foreach(var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
-      CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
-      if(${var} MATCHES "/MD")
-        string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}")
-      endif()
-    endforeach()
-  endif()
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3 /wd4996")
-endif()
-
-if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
-  # Use the maximum optimization level for release builds
-  foreach(var CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO)
-    if(${var} MATCHES "-O2")
-      string(REGEX REPLACE "-O2" "-O3" ${var} "${${var}}")
-    endif()
-  endforeach()
-endif()
-
-if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
-  if(CMAKE_C_COMPILER_ID MATCHES "SunPro")
-    # Use the maximum optimization level for release builds
-    foreach(var CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO)
-      if(${var} MATCHES "-xO3")
-        string(REGEX REPLACE "-xO3" "-xO5" ${var} "${${var}}")
-      endif()
-      if(${var} MATCHES "-xO2")
-        string(REGEX REPLACE "-xO2" "-xO5" ${var} "${${var}}")
-      endif()
-    endforeach()
-  endif()
-endif()
-
-string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC)
-
-set(EFFECTIVE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
-message(STATUS "Compiler flags = ${EFFECTIVE_C_FLAGS}")
-
-set(EFFECTIVE_LD_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
-message(STATUS "Linker flags = ${EFFECTIVE_LD_FLAGS}")
-
-include(CheckCSourceCompiles)
-include(CheckIncludeFiles)
-include(CheckTypeSize)
-
-check_type_size("size_t" SIZE_T)
-check_type_size("unsigned long" UNSIGNED_LONG)
-
-if(SIZE_T EQUAL UNSIGNED_LONG)
-  check_c_source_compiles("int main(int argc, char **argv) { unsigned long a = argc;  return __builtin_ctzl(a); }"
-    HAVE_BUILTIN_CTZL)
-endif()
-if(MSVC)
-  check_include_files("intrin.h" HAVE_INTRIN_H)
-endif()
-
-if(UNIX)
-  # Check for headers
-  check_include_files(locale.h HAVE_LOCALE_H)
-  check_include_files(stddef.h HAVE_STDDEF_H)
-  check_include_files(stdlib.h HAVE_STDLIB_H)
-  check_include_files(sys/types.h NEED_SYS_TYPES_H)
-
-  # Check for functions
-  include(CheckSymbolExists)
-  check_symbol_exists(memset string.h HAVE_MEMSET)
-  check_symbol_exists(memcpy string.h HAVE_MEMCPY)
-  if(NOT HAVE_MEMSET AND NOT HAVE_MEMCPY)
-    set(NEED_BSD_STRINGS 1)
-  endif()
-
-  # Check for types
-  check_type_size("unsigned char" UNSIGNED_CHAR)
-  check_type_size("unsigned short" UNSIGNED_SHORT)
-
-  # Check for compiler features
-  check_c_source_compiles("int main(void) { typedef struct undefined_structure *undef_struct_ptr;  undef_struct_ptr ptr = 0;  return ptr != 0; }"
-    INCOMPLETE_TYPES)
-  if(INCOMPLETE_TYPES)
-    message(STATUS "Compiler supports pointers to undefined structures.")
-  else()
-    set(INCOMPLETE_TYPES_BROKEN 1)
-    message(STATUS "Compiler does not support pointers to undefined structures.")
-  endif()
-
-  if(CMAKE_CROSSCOMPILING)
-    set(RIGHT_SHIFT_IS_UNSIGNED 0)
-  else()
-    include(CheckCSourceRuns)
-    check_c_source_runs("
-      #include <stdio.h>
-      #include <stdlib.h>
-      int is_shifting_signed (long arg) {
-        long res = arg >> 4;
-        if (res == -0x7F7E80CL)
-          return 1; /* right shift is signed */
-        /* see if unsigned-shift hack will fix it. */
-        /* we can't just test exact value since it depends on width of long... */
-        res |= (~0L) << (32-4);
-        if (res == -0x7F7E80CL)
-          return 0; /* right shift is unsigned */
-        printf(\"Right shift isn't acting as I expect it to.\\\\n\");
-        printf(\"I fear the JPEG software will not work at all.\\\\n\\\\n\");
-        return 0; /* try it with unsigned anyway */
-      }
-      int main (void) {
-        exit(is_shifting_signed(-0x7F7E80B1L));
-      }" RIGHT_SHIFT_IS_UNSIGNED)
-  endif()
-
-  if(CMAKE_CROSSCOMPILING)
-    set(__CHAR_UNSIGNED__ 0)
-  else()
-    check_c_source_runs("int main(void) { return ((char) -1 < 0); }"
-      __CHAR_UNSIGNED__)
-  endif()
-endif()
-
-if(MSVC)
-  set(INLINE_OPTIONS "__inline;inline")
-else()
-  set(INLINE_OPTIONS "__inline__;inline")
-endif()
-option(FORCE_INLINE "Force function inlining" TRUE)
-boolean_number(FORCE_INLINE)
-if(FORCE_INLINE)
-  if(MSVC)
-    list(INSERT INLINE_OPTIONS 0 "__forceinline")
-  else()
-    list(INSERT INLINE_OPTIONS 0 "inline __attribute__((always_inline))")
-    list(INSERT INLINE_OPTIONS 0 "__inline__ __attribute__((always_inline))")
-  endif()
-endif()
-foreach(inline ${INLINE_OPTIONS})
-  check_c_source_compiles("${inline} static int foo(void) { return 0; } int main(void) { return foo(); }"
-    INLINE_WORKS)
-  if(INLINE_WORKS)
-    set(INLINE ${inline})
-    break()
-  endif()
-endforeach()
-if(NOT INLINE_WORKS)
-  message(FATAL_ERROR "Could not determine how to inline functions.")
-endif()
-message(STATUS "INLINE = ${INLINE} (FORCE_INLINE = ${FORCE_INLINE})")
-
-if(UNIX AND NOT APPLE)
-  file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/conftest.map "VERS_1 { global: *; };")
-  set(CMAKE_REQUIRED_FLAGS
-    "-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
-  check_c_source_compiles("int main(void) { return 0; }" HAVE_VERSION_SCRIPT)
-  set(CMAKE_REQUIRED_FLAGS)
-  file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/conftest.map)
-  if(HAVE_VERSION_SCRIPT)
-    message(STATUS "Linker supports GNU-style version scripts")
-    set(MAPFLAG "-Wl,--version-script,")
-    set(TJMAPFLAG "-Wl,--version-script,")
-  else()
-    message(STATUS "Linker does not support GNU-style version scripts")
-    if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
-      # The Solaris linker doesn't like our version script for the libjpeg API
-      # library, but the version script for the TurboJPEG API library should
-      # still work.
-      file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/conftest.map
-        "VERS_1 { global: foo;  local: *; }; VERS_2 { global: foo2; } VERS_1;")
-      set(CMAKE_REQUIRED_FLAGS "-Wl,-M,${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
-      check_c_source_compiles("void foo() {} void foo2() {} int main(void) { return 0; }"
-        HAVE_MAPFILE)
-      set(CMAKE_REQUIRED_FLAGS)
-      file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/conftest.map)
-      if(HAVE_MAPFILE)
-        message(STATUS "Linker supports mapfiles")
-        set(TJMAPFLAG "-Wl,-M,")
-      else()
-        message(STATUS "Linker does not support mapfiles")
-      endif()
-    endif()
-  endif()
-endif()
-
-# Generate files
-if(WIN32)
-  configure_file(win/jconfig.h.in jconfig.h)
-else()
-  configure_file(jconfig.h.in jconfig.h)
-endif()
-configure_file(jconfigint.h.in jconfigint.h)
-if(UNIX)
-  configure_file(libjpeg.map.in libjpeg.map)
-endif()
-
-# Include directories and compiler definitions
-include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
-
-
-###############################################################################
-# TARGETS
-###############################################################################
-
-set(JPEG_SOURCES jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c
-  jcicc.c jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c
-  jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c jdatadst.c
-  jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c jdicc.c jdinput.c
-  jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c jdpostct.c jdsample.c
-  jdtrans.c jerror.c jfdctflt.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c
-  jidctint.c jidctred.c jquant1.c jquant2.c jutils.c jmemmgr.c jmemnobs.c)
-
-if(WITH_ARITH_ENC OR WITH_ARITH_DEC)
-  set(JPEG_SOURCES ${JPEG_SOURCES} jaricom.c)
-endif()
-
-if(WITH_ARITH_ENC)
-  set(JPEG_SOURCES ${JPEG_SOURCES} jcarith.c)
-endif()
-
-if(WITH_ARITH_DEC)
-  set(JPEG_SOURCES ${JPEG_SOURCES} jdarith.c)
-endif()
-
-if(WITH_SIMD)
-  add_subdirectory(simd)
-elseif(NOT WITH_12BIT)
-  message(STATUS "SIMD extensions: None (WITH_SIMD = ${WITH_SIMD})")
-endif()
-if(WITH_SIMD)
-  message(STATUS "SIMD extensions: ${CPU_TYPE} (WITH_SIMD = ${WITH_SIMD})")
-  if(MSVC_IDE)
-    set_source_files_properties(${SIMD_OBJS} PROPERTIES GENERATED 1)
-  endif()
-else()
-  add_library(simd OBJECT jsimd_none.c)
-endif()
-
-if(WITH_JAVA)
-  add_subdirectory(java)
-endif()
-
-if(ENABLE_SHARED)
-  add_subdirectory(sharedlib)
-endif()
-
-if(ENABLE_STATIC)
-  add_library(jpeg-static STATIC ${JPEG_SOURCES} $<TARGET_OBJECTS:simd>
-    ${SIMD_OBJS})
-  if(NOT MSVC)
-    set_target_properties(jpeg-static PROPERTIES OUTPUT_NAME jpeg)
-  endif()
-endif()
-
-if(WITH_TURBOJPEG)
-  if(ENABLE_SHARED)
-    set(TURBOJPEG_SOURCES ${JPEG_SOURCES} $<TARGET_OBJECTS:simd> ${SIMD_OBJS}
-      turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c rdbmp.c rdppm.c
-      wrbmp.c wrppm.c)
-    set(TJMAPFILE ${CMAKE_CURRENT_SOURCE_DIR}/turbojpeg-mapfile)
-    if(WITH_JAVA)
-      set(TURBOJPEG_SOURCES ${TURBOJPEG_SOURCES} turbojpeg-jni.c)
-      include_directories(${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
-      set(TJMAPFILE ${CMAKE_CURRENT_SOURCE_DIR}/turbojpeg-mapfile.jni)
-    endif()
-    add_library(turbojpeg SHARED ${TURBOJPEG_SOURCES})
-    set_property(TARGET turbojpeg PROPERTY COMPILE_FLAGS
-      "-DBMP_SUPPORTED -DPPM_SUPPORTED")
-    if(WIN32)
-      set_target_properties(turbojpeg PROPERTIES DEFINE_SYMBOL DLLDEFINE)
-    endif()
-    if(MINGW)
-      set_target_properties(turbojpeg PROPERTIES LINK_FLAGS -Wl,--kill-at)
-    endif()
-    if(APPLE)
-      if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG)
-        set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,")
-      endif()
-      set_target_properties(turbojpeg PROPERTIES MACOSX_RPATH 1)
-    endif()
-    set_target_properties(turbojpeg PROPERTIES
-      SOVERSION ${TURBOJPEG_SO_MAJOR_VERSION} VERSION ${TURBOJPEG_SO_VERSION})
-    if(TJMAPFLAG)
-      set_target_properties(turbojpeg PROPERTIES
-        LINK_FLAGS "${TJMAPFLAG}${TJMAPFILE}")
-    endif()
-
-    add_executable(tjunittest tjunittest.c tjutil.c md5/md5.c md5/md5hl.c)
-    target_link_libraries(tjunittest turbojpeg)
-
-    add_executable(tjbench tjbench.c tjutil.c)
-    target_link_libraries(tjbench turbojpeg)
-    if(UNIX)
-      target_link_libraries(tjbench m)
-    endif()
-
-    add_executable(tjexample tjexample.c)
-    target_link_libraries(tjexample turbojpeg)
-  endif()
-
-  if(ENABLE_STATIC)
-    add_library(turbojpeg-static STATIC ${JPEG_SOURCES} $<TARGET_OBJECTS:simd>
-      ${SIMD_OBJS} turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c rdbmp.c
-      rdppm.c wrbmp.c wrppm.c)
-    set_property(TARGET turbojpeg-static PROPERTY COMPILE_FLAGS
-      "-DBMP_SUPPORTED -DPPM_SUPPORTED")
-    if(NOT MSVC)
-      set_target_properties(turbojpeg-static PROPERTIES OUTPUT_NAME turbojpeg)
-    endif()
-
-    add_executable(tjunittest-static tjunittest.c tjutil.c md5/md5.c
-      md5/md5hl.c)
-    target_link_libraries(tjunittest-static turbojpeg-static)
-
-    add_executable(tjbench-static tjbench.c tjutil.c)
-    target_link_libraries(tjbench-static turbojpeg-static)
-    if(UNIX)
-      target_link_libraries(tjbench-static m)
-    endif()
-  endif()
-endif()
-
-if(WIN32)
-  set(USE_SETMODE "-DUSE_SETMODE")
-endif()
-if(WITH_12BIT)
-  set(COMPILE_FLAGS "-DGIF_SUPPORTED -DPPM_SUPPORTED ${USE_SETMODE}")
-else()
-  set(COMPILE_FLAGS "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED ${USE_SETMODE}")
-  set(CJPEG_BMP_SOURCES rdbmp.c rdtarga.c)
-  set(DJPEG_BMP_SOURCES wrbmp.c wrtarga.c)
-endif()
-
-if(ENABLE_STATIC)
-  add_executable(cjpeg-static cjpeg.c cdjpeg.c rdgif.c rdppm.c rdswitch.c
-    ${CJPEG_BMP_SOURCES})
-  set_property(TARGET cjpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS})
-  target_link_libraries(cjpeg-static jpeg-static)
-
-  add_executable(djpeg-static djpeg.c cdjpeg.c rdcolmap.c rdswitch.c wrgif.c
-    wrppm.c ${DJPEG_BMP_SOURCES})
-  set_property(TARGET djpeg-static PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS})
-  target_link_libraries(djpeg-static jpeg-static)
-
-  add_executable(jpegtran-static jpegtran.c cdjpeg.c rdswitch.c transupp.c)
-  target_link_libraries(jpegtran-static jpeg-static)
-  set_property(TARGET jpegtran-static PROPERTY COMPILE_FLAGS "${USE_SETMODE}")
-endif()
-
-add_executable(rdjpgcom rdjpgcom.c)
-
-add_executable(wrjpgcom wrjpgcom.c)
-
-
-###############################################################################
-# TESTS
-###############################################################################
-
-add_subdirectory(md5)
-
-if(MSVC_IDE)
-  set(OBJDIR "\${CTEST_CONFIGURATION_TYPE}/")
-else()
-  set(OBJDIR "")
-endif()
-
-enable_testing()
-
-if(WITH_12BIT)
-  set(TESTORIG testorig12.jpg)
-  set(MD5_JPEG_RGB_ISLOW 9d7369207c520d37f2c1cbfcb82b2964)
-  set(MD5_JPEG_RGB_ISLOW2 a00bd20d8ae49684640ef7177d2e0b64)
-  set(MD5_PPM_RGB_ISLOW f3301d2219783b8b3d942b7239fa50c0)
-  set(MD5_JPEG_422_IFAST_OPT 7322e3bd2f127f7de4b40d4480ce60e4)
-  set(MD5_PPM_422_IFAST 79807fa552899e66a04708f533e16950)
-  set(MD5_PPM_422M_IFAST 07737bfe8a7c1c87aaa393a0098d16b0)
-  set(MD5_JPEG_420_IFAST_Q100_PROG a1da220b5604081863a504297ed59e55)
-  set(MD5_PPM_420_Q100_IFAST 1b3730122709f53d007255e8dfd3305e)
-  set(MD5_PPM_420M_Q100_IFAST 980a1a3c5bf9510022869d30b7d26566)
-  set(MD5_JPEG_GRAY_ISLOW 235c90707b16e2e069f37c888b2636d9)
-  set(MD5_PPM_GRAY_ISLOW 7213c10af507ad467da5578ca5ee1fca)
-  set(MD5_PPM_GRAY_ISLOW_RGB e96ee81c30a6ed422d466338bd3de65d)
-  set(MD5_JPEG_420S_IFAST_OPT 7af8e60be4d9c227ec63ac9b6630855e)
-
-  set(MD5_JPEG_3x2_FLOAT_PROG_SSE a8c17daf77b457725ec929e215b603f8)
-  set(MD5_PPM_3x2_FLOAT_SSE 42876ab9e5c2f76a87d08db5fbd57956)
-  set(MD5_JPEG_3x2_FLOAT_PROG_32BIT a8c17daf77b457725ec929e215b603f8)
-  set(MD5_PPM_3x2_FLOAT_32BIT ${MD5_PPM_3x2_FLOAT_SSE})
-  set(MD5_JPEG_3x2_FLOAT_PROG_64BIT ${MD5_JPEG_3x2_FLOAT_PROG_32BIT})
-  set(MD5_PPM_3x2_FLOAT_64BIT ${MD5_PPM_3x2_FLOAT_SSE})
-  set(MD5_JPEG_3x2_FLOAT_PROG_387 bc6dbbefac2872f6b9d6c4a0ae60c3c0)
-  set(MD5_PPM_3x2_FLOAT_387 bcc5723c61560463ac60f772e742d092)
-  set(MD5_JPEG_3x2_FLOAT_PROG_MSVC e27840755870fa849872e58aa0cd1400)
-  set(MD5_PPM_3x2_FLOAT_MSVC 6c2880b83bb1aa41dfe330e7a9768690)
-
-  set(MD5_JPEG_3x2_IFAST_PROG 1396cc2b7185cfe943d408c9d305339e)
-  set(MD5_PPM_3x2_IFAST 3975985ef6eeb0a2cdc58daa651ccc00)
-  set(MD5_PPM_420M_ISLOW_2_1 4ca6be2a6f326ff9eaab63e70a8259c0)
-  set(MD5_PPM_420M_ISLOW_15_8 12aa9f9534c1b3d7ba047322226365eb)
-  set(MD5_PPM_420M_ISLOW_13_8 f7e22817c7b25e1393e4ec101e9d4e96)
-  set(MD5_PPM_420M_ISLOW_11_8 800a16f9f4dc9b293197bfe11be10a82)
-  set(MD5_PPM_420M_ISLOW_9_8 06b7a92a9bc69f4dc36ec40f1937d55c)
-  set(MD5_PPM_420M_ISLOW_7_8 3ec444a14a4ab4eab88ffc49c48eca43)
-  set(MD5_PPM_420M_ISLOW_3_4 3e726b7ea872445b19437d1c1d4f0d93)
-  set(MD5_PPM_420M_ISLOW_5_8 a8a771abdc94301d20ffac119b2caccd)
-  set(MD5_PPM_420M_ISLOW_1_2 b419124dd5568b085787234866102866)
-  set(MD5_PPM_420M_ISLOW_3_8 343d19015531b7bbe746124127244fa8)
-  set(MD5_PPM_420M_ISLOW_1_4 35fd59d866e44659edfa3c18db2a3edb)
-  set(MD5_PPM_420M_ISLOW_1_8 ccaed48ac0aedefda5d4abe4013f4ad7)
-  set(MD5_PPM_420_ISLOW_SKIP15_31 86664cd9dc956536409e44e244d20a97)
-  set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 452a21656115a163029cfba5c04fa76a)
-  set(MD5_PPM_444_ISLOW_SKIP1_6 ef63901f71ef7a75cd78253fc0914f84)
-  set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 15b173fb5872d9575572fbcc1b05956f)
-  set(MD5_JPEG_CROP cdb35ff4b4519392690ea040c56ea99c)
-else()
-  set(TESTORIG testorig.jpg)
-  set(MD5_JPEG_RGB_ISLOW 1d44a406f61da743b5fd31c0a9abdca3)
-  set(MD5_JPEG_RGB_ISLOW2 31d121e57b6c2934c890a7fc7763bcd4)
-  set(MD5_PPM_RGB_ISLOW 00a257f5393fef8821f2b88ac7421291)
-  set(MD5_BMP_RGB_ISLOW_565 f07d2e75073e4bb10f6c6f4d36e2e3be)
-  set(MD5_BMP_RGB_ISLOW_565D 4cfa0928ef3e6bb626d7728c924cfda4)
-  set(MD5_JPEG_422_IFAST_OPT 2540287b79d913f91665e660303ab2c8)
-  set(MD5_PPM_422_IFAST 35bd6b3f833bad23de82acea847129fa)
-  set(MD5_PPM_422M_IFAST 8dbc65323d62cca7c91ba02dd1cfa81d)
-  set(MD5_BMP_422M_IFAST_565 3294bd4d9a1f2b3d08ea6020d0db7065)
-  set(MD5_BMP_422M_IFAST_565D da98c9c7b6039511be4a79a878a9abc1)
-  set(MD5_JPEG_420_IFAST_Q100_PROG 990cbe0329c882420a2094da7e5adade)
-  set(MD5_PPM_420_Q100_IFAST 5a732542015c278ff43635e473a8a294)
-  set(MD5_PPM_420M_Q100_IFAST ff692ee9323a3b424894862557c092f1)
-  set(MD5_JPEG_GRAY_ISLOW 72b51f894b8f4a10b3ee3066770aa38d)
-  set(MD5_PPM_GRAY_ISLOW 8d3596c56eace32f205deccc229aa5ed)
-  set(MD5_PPM_GRAY_ISLOW_RGB 116424ac07b79e5e801f00508eab48ec)
-  set(MD5_BMP_GRAY_ISLOW_565 12f78118e56a2f48b966f792fedf23cc)
-  set(MD5_BMP_GRAY_ISLOW_565D bdbbd616441a24354c98553df5dc82db)
-  set(MD5_JPEG_420S_IFAST_OPT 388708217ac46273ca33086b22827ed8)
-
-  set(MD5_JPEG_3x2_FLOAT_PROG_SSE 343e3f8caf8af5986ebaf0bdc13b5c71)
-  set(MD5_PPM_3x2_FLOAT_SSE 1a75f36e5904d6fc3a85a43da9ad89bb)
-  set(MD5_JPEG_3x2_FLOAT_PROG_32BIT 9bca803d2042bd1eb03819e2bf92b3e5)
-  set(MD5_PPM_3x2_FLOAT_32BIT f6bfab038438ed8f5522fbd33595dcdc)
-  set(MD5_JPEG_3x2_FLOAT_PROG_64BIT ${MD5_JPEG_3x2_FLOAT_PROG_32BIT})
-  set(MD5_PPM_3x2_FLOAT_64BIT 0e917a34193ef976b679a6b069b1be26)
-  set(MD5_JPEG_3x2_FLOAT_PROG_387 1657664a410e0822c924b54f6f65e6e9)
-  set(MD5_PPM_3x2_FLOAT_387 cb0a1f027f3d2917c902b5640214e025)
-  set(MD5_JPEG_3x2_FLOAT_PROG_MSVC 7999ce9cd0ee9b6c7043b7351ab7639d)
-  set(MD5_PPM_3x2_FLOAT_MSVC 28cdc448a6b75e97892f0e0f8d4b21f3)
-
-  set(MD5_JPEG_3x2_IFAST_PROG 1ee5d2c1a77f2da495f993c8c7cceca5)
-  set(MD5_PPM_3x2_IFAST fd283664b3b49127984af0a7f118fccd)
-  set(MD5_JPEG_420_ISLOW_ARI e986fb0a637a8d833d96e8a6d6d84ea1)
-  set(MD5_JPEG_444_ISLOW_PROGARI 0a8f1c8f66e113c3cf635df0a475a617)
-  set(MD5_PPM_420M_IFAST_ARI 72b59a99bcf1de24c5b27d151bde2437)
-  set(MD5_JPEG_420_ISLOW 9a68f56bc76e466aa7e52f415d0f4a5f)
-  set(MD5_PPM_420M_ISLOW_2_1 9f9de8c0612f8d06869b960b05abf9c9)
-  set(MD5_PPM_420M_ISLOW_15_8 b6875bc070720b899566cc06459b63b7)
-  set(MD5_PPM_420M_ISLOW_13_8 bc3452573c8152f6ae552939ee19f82f)
-  set(MD5_PPM_420M_ISLOW_11_8 d8cc73c0aaacd4556569b59437ba00a5)
-  set(MD5_PPM_420M_ISLOW_9_8 d25e61bc7eac0002f5b393aa223747b6)
-  set(MD5_PPM_420M_ISLOW_7_8 ddb564b7c74a09494016d6cd7502a946)
-  set(MD5_PPM_420M_ISLOW_3_4 8ed8e68808c3fbc4ea764fc9d2968646)
-  set(MD5_PPM_420M_ISLOW_5_8 a3363274999da2366a024efae6d16c9b)
-  set(MD5_PPM_420M_ISLOW_1_2 e692a315cea26b988c8e8b29a5dbcd81)
-  set(MD5_PPM_420M_ISLOW_3_8 79eca9175652ced755155c90e785a996)
-  set(MD5_PPM_420M_ISLOW_1_4 79cd778f8bf1a117690052cacdd54eca)
-  set(MD5_PPM_420M_ISLOW_1_8 391b3d4aca640c8567d6f8745eb2142f)
-  set(MD5_BMP_420_ISLOW_256 4980185e3776e89bd931736e1cddeee6)
-  set(MD5_BMP_420_ISLOW_565 bf9d13e16c4923b92e1faa604d7922cb)
-  set(MD5_BMP_420_ISLOW_565D 6bde71526acc44bcff76f696df8638d2)
-  set(MD5_BMP_420M_ISLOW_565 8dc0185245353cfa32ad97027342216f)
-  set(MD5_BMP_420M_ISLOW_565D ce034037d212bc403330df6f915c161b)
-  set(MD5_PPM_420_ISLOW_SKIP15_31 c4c65c1e43d7275cd50328a61e6534f0)
-  set(MD5_PPM_420_ISLOW_ARI_SKIP16_139 087c6b123db16ac00cb88c5b590bb74a)
-  set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 26eb36ccc7d1f0cb80cdabb0ac8b5d99)
-  set(MD5_PPM_420_ISLOW_ARI_CROP53x53_4_4 886c6775af22370257122f8b16207e6d)
-  set(MD5_PPM_444_ISLOW_SKIP1_6 5606f86874cf26b8fcee1117a0a436a6)
-  set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 db87dc7ce26bcdc7a6b56239ce2b9d6c)
-  set(MD5_PPM_444_ISLOW_ARI_CROP37x37_0_0 cb57b32bd6d03e35432362f7bf184b6d)
-  set(MD5_JPEG_CROP b4197f377e621c4e9b1d20471432610d)
-endif()
-
-if(WITH_JAVA)
-  add_test(TJUnitTest
-    ${Java_JAVA_EXECUTABLE} ${JAVAARGS} -cp java/turbojpeg.jar
-      -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}
-      TJUnitTest)
-  add_test(TJUnitTest-yuv
-    ${Java_JAVA_EXECUTABLE} ${JAVAARGS} -cp java/turbojpeg.jar
-      -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}
-      TJUnitTest -yuv)
-  add_test(TJUnitTest-yuv-nopad
-    ${Java_JAVA_EXECUTABLE} ${JAVAARGS} -cp java/turbojpeg.jar
-      -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}
-      TJUnitTest -yuv -noyuvpad)
-  add_test(TJUnitTest-bi
-    ${Java_JAVA_EXECUTABLE} ${JAVAARGS} -cp java/turbojpeg.jar
-      -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}
-      TJUnitTest -bi)
-  add_test(TJUnitTest-bi-yuv
-    ${Java_JAVA_EXECUTABLE} ${JAVAARGS} -cp java/turbojpeg.jar
-      -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}
-      TJUnitTest -bi -yuv)
-  add_test(TJUnitTest-bi-yuv-nopad
-    ${Java_JAVA_EXECUTABLE} ${JAVAARGS} -cp java/turbojpeg.jar
-      -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR}
-      TJUnitTest -bi -yuv -noyuvpad)
-endif()
-
-set(TEST_LIBTYPES "")
-if(ENABLE_SHARED)
-  set(TEST_LIBTYPES ${TEST_LIBTYPES} shared)
-endif()
-if(ENABLE_STATIC)
-  set(TEST_LIBTYPES ${TEST_LIBTYPES} static)
-endif()
-
-set(TESTIMAGES ${CMAKE_CURRENT_SOURCE_DIR}/testimages)
-set(MD5CMP ${CMAKE_CURRENT_BINARY_DIR}/md5/md5cmp)
-if(CMAKE_CROSSCOMPILING)
-  file(RELATIVE_PATH TESTIMAGES ${CMAKE_CURRENT_BINARY_DIR} ${TESTIMAGES})
-  file(RELATIVE_PATH MD5CMP ${CMAKE_CURRENT_BINARY_DIR} ${MD5CMP})
-endif()
-
-# The output of the floating point DCT/IDCT algorithms differs depending on the
-# type of floating point math used, so the FLOATTEST CMake variable must be
-# set in order to tell the testing system which floating point results it
-# should expect:
-#
-# sse = validate against the expected results from the libjpeg-turbo SSE SIMD
-#       extensions
-# 32bit = validate against the expected results from the C code when running on
-#         a 32-bit FPU (or when SSE is being used for floating point math,
-#         which is generally the default with x86-64 compilers)
-# 64bit = validate against the expected results from the C code when running
-#         on a 64-bit FPU
-# 387 = validate against the expected results from the C code when the 387 FPU
-#       is being used for floating point math (which is generally the default
-#       with x86 compilers)
-# msvc = validate against the expected results from the C code when compiled
-#        with a 32-bit version of Visual C++
-
-if(CPU_TYPE STREQUAL "x86_64" OR CPU_TYPE STREQUAL "i386")
-  if(WITH_SIMD)
-    set(DEFAULT_FLOATTEST sse)
-  elseif(CPU_TYPE STREQUAL "x86_64")
-    set(DEFAULT_FLOATTEST 32bit)
-  elseif(CPU_TYPE STREQUAL "i386" AND MSVC)
-    set(DEFAULT_FLOATTEST msvc)
-  endif()
-else()
-  if(BITS EQUAL 64)
-    set(DEFAULT_FLOATTEST 64bit)
-  elseif(BITS EQUAL 32)
-    set(DEFAULT_FLOATTEST 32bit)
-  endif()
-endif()
-
-# This causes FLOATTEST to reset to the default value if WITH_SIMD has
-# changed.
-if(DEFINED WITH_SIMD_INT AND NOT WITH_SIMD EQUAL WITH_SIMD_INT)
-  set(FORCE_FLOATTEST "FORCE")
-endif()
-set(WITH_SIMD_INT ${WITH_SIMD} CACHE INTERNAL "")
-set(FLOATTEST ${DEFAULT_FLOATTEST} CACHE STRING
-  "The type of floating point math used by the floating point DCT/IDCT algorithms.  This tells the testing system which numerical results it should expect from those tests.  [sse = libjpeg-turbo x86/x86-64 SIMD extensions, 32bit = generic 32-bit FPU or SSE, 64bit = generic 64-bit FPU, 387 = 387 FPU, msvc = 32-bit Visual Studio] (default = ${DEFAULT_FLOATTEST})"
-  ${FORCE_FLOATTEST})
-message(STATUS "FLOATTEST = ${FLOATTEST}")
-
-if(FLOATTEST)
-  string(TOUPPER ${FLOATTEST} FLOATTEST_UC)
-  string(TOLOWER ${FLOATTEST} FLOATTEST)
-  if(NOT FLOATTEST STREQUAL "sse" AND NOT FLOATTEST STREQUAL "32bit" AND
-    NOT FLOATTEST STREQUAL "64bit" AND NOT FLOATTEST STREQUAL "387" AND
-    NOT FLOATTEST STREQUAL "msvc")
-    message(FATAL_ERROR "\"${FLOATTEST}\" is not a valid value for FLOATTEST.")
-  endif()
-endif()
-
-foreach(libtype ${TEST_LIBTYPES})
-  if(libtype STREQUAL "static")
-    set(suffix -static)
-  endif()
-  if(WITH_TURBOJPEG)
-    add_test(tjunittest-${libtype} tjunittest${suffix})
-    add_test(tjunittest-${libtype}-alloc tjunittest${suffix} -alloc)
-    add_test(tjunittest-${libtype}-yuv tjunittest${suffix} -yuv)
-    add_test(tjunittest-${libtype}-yuv-alloc tjunittest${suffix} -yuv -alloc)
-    add_test(tjunittest-${libtype}-yuv-nopad tjunittest${suffix} -yuv -noyuvpad)
-    add_test(tjunittest-${libtype}-bmp tjunittest${suffix} -bmp)
-
-    set(MD5_PPM_GRAY_TILE 89d3ca21213d9d864b50b4e4e7de4ca6)
-    set(MD5_PPM_420_8x8_TILE 847fceab15c5b7b911cb986cf0f71de3)
-    set(MD5_PPM_420_16x16_TILE ca45552a93687e078f7137cc4126a7b0)
-    set(MD5_PPM_420_32x32_TILE d8676f1d6b68df358353bba9844f4a00)
-    set(MD5_PPM_420_64x64_TILE 4e4c1a3d7ea4bace4f868bcbe83b7050)
-    set(MD5_PPM_420_128x128_TILE f24c3429c52265832beab9df72a0ceae)
-    set(MD5_PPM_420M_8x8_TILE bc25320e1f4c31ce2e610e43e9fd173c)
-    set(MD5_PPM_420M_TILE 75ffdf14602258c5c189522af57fa605)
-    set(MD5_PPM_422_8x8_TILE d83dacd9fc73b0a6f10c09acad64eb1e)
-    set(MD5_PPM_422_16x16_TILE 35077fb610d72dd743b1eb0cbcfe10fb)
-    set(MD5_PPM_422_32x32_TILE e6902ed8a449ecc0f0d6f2bf945f65f7)
-    set(MD5_PPM_422_64x64_TILE 2b4502a8f316cedbde1da7bce3d2231e)
-    set(MD5_PPM_422_128x128_TILE f0b5617d578f5e13c8eee215d64d4877)
-    set(MD5_PPM_422M_8x8_TILE 828941d7f41cd6283abd6beffb7fd51d)
-    set(MD5_PPM_422M_TILE e877ae1324c4a280b95376f7f018172f)
-    set(MD5_PPM_444_TILE 7964e41e67cfb8d0a587c0aa4798f9c3)
-
-    # Test compressing from/decompressing to an arbitrary subregion of a larger
-    # image buffer
-    add_test(tjbench-${libtype}-tile-cp
-      ${CMAKE_COMMAND} -E copy_if_different ${TESTIMAGES}/testorig.ppm
-        testout_tile.ppm)
-    add_test(tjbench-${libtype}-tile
-      tjbench${suffix} testout_tile.ppm 95 -rgb -quiet -tile -benchtime 0.01
-        -warmup 0)
-    set_tests_properties(tjbench-${libtype}-tile
-      PROPERTIES DEPENDS tjbench-${libtype}-tile-cp)
-
-    foreach(tile 8 16 32 64 128)
-      add_test(tjbench-${libtype}-tile-gray-${tile}x${tile}-cmp
-        ${MD5CMP} ${MD5_PPM_GRAY_TILE}
-          testout_tile_GRAY_Q95_${tile}x${tile}.ppm)
-      foreach(subsamp 420 422)
-        add_test(tjbench-${libtype}-tile-${subsamp}-${tile}x${tile}-cmp
-          ${MD5CMP} ${MD5_PPM_${subsamp}_${tile}x${tile}_TILE}
-            testout_tile_${subsamp}_Q95_${tile}x${tile}.ppm)
-      endforeach()
-      add_test(tjbench-${libtype}-tile-444-${tile}x${tile}-cmp
-        ${MD5CMP} ${MD5_PPM_444_TILE}
-          testout_tile_444_Q95_${tile}x${tile}.ppm)
-      foreach(subsamp gray 420 422 444)
-        set_tests_properties(tjbench-${libtype}-tile-${subsamp}-${tile}x${tile}-cmp
-          PROPERTIES DEPENDS tjbench-${libtype}-tile)
-      endforeach()
-    endforeach()
-
-    add_test(tjbench-${libtype}-tilem-cp
-      ${CMAKE_COMMAND} -E copy_if_different ${TESTIMAGES}/testorig.ppm
-        testout_tilem.ppm)
-    add_test(tjbench-${libtype}-tilem
-      tjbench${suffix} testout_tilem.ppm 95 -rgb -fastupsample -quiet -tile
-        -benchtime 0.01 -warmup 0)
-    set_tests_properties(tjbench-${libtype}-tilem
-      PROPERTIES DEPENDS tjbench-${libtype}-tilem-cp)
-
-    add_test(tjbench-${libtype}-tile-420m-8x8-cmp
-      ${MD5CMP} ${MD5_PPM_420M_8x8_TILE} testout_tilem_420_Q95_8x8.ppm)
-    add_test(tjbench-${libtype}-tile-422m-8x8-cmp
-      ${MD5CMP} ${MD5_PPM_422M_8x8_TILE} testout_tilem_422_Q95_8x8.ppm)
-    foreach(tile 16 32 64 128)
-      foreach(subsamp 420 422)
-        add_test(tjbench-${libtype}-tile-${subsamp}m-${tile}x${tile}-cmp
-          ${MD5CMP} ${MD5_PPM_${subsamp}M_TILE}
-            testout_tilem_${subsamp}_Q95_${tile}x${tile}.ppm)
-      endforeach()
-    endforeach()
-    foreach(tile 8 16 32 64 128)
-      foreach(subsamp 420 422)
-        set_tests_properties(tjbench-${libtype}-tile-${subsamp}m-${tile}x${tile}-cmp
-          PROPERTIES DEPENDS tjbench-${libtype}-tilem)
-      endforeach()
-    endforeach()
-  endif()
-
-  # These tests are carefully crafted to provide full coverage of as many of
-  # the underlying algorithms as possible (including all of the
-  # SIMD-accelerated ones.)
-
-  macro(add_bittest PROG NAME ARGS OUTFILE INFILE MD5SUM)
-    add_test(${PROG}-${libtype}-${NAME}
-      ${PROG}${suffix} ${ARGS} -outfile ${OUTFILE} ${INFILE})
-    add_test(${PROG}-${libtype}-${NAME}-cmp
-      ${MD5CMP} ${MD5SUM} ${OUTFILE})
-    set_tests_properties(${PROG}-${libtype}-${NAME}-cmp PROPERTIES
-      DEPENDS ${PROG}-${libtype}-${NAME})
-    if(${ARGC} GREATER 6)
-      set(DEPENDS ${ARGN})
-      set_tests_properties(${PROG}-${libtype}-${NAME} PROPERTIES
-        DEPENDS ${DEPENDS})
-    endif()
-  endmacro()
-
-  # CC: null  SAMP: fullsize  FDCT: islow  ENT: huff
-  add_bittest(cjpeg rgb-islow "-rgb;-dct;int;-icc;${TESTIMAGES}/test1.icc"
-    testout_rgb_islow.jpg ${TESTIMAGES}/testorig.ppm
-    ${MD5_JPEG_RGB_ISLOW})
-
-  # CC: null  SAMP: fullsize  IDCT: islow  ENT: huff
-  add_bittest(djpeg rgb-islow "-dct;int;-ppm;-icc;testout_rgb_islow.icc"
-    testout_rgb_islow.ppm testout_rgb_islow.jpg
-    ${MD5_PPM_RGB_ISLOW} cjpeg-${libtype}-rgb-islow)
-
-  add_test(djpeg-${libtype}-rgb-islow-icc-cmp
-    ${MD5CMP} b06a39d730129122e85c1363ed1bbc9e testout_rgb_islow.icc)
-
-  add_bittest(jpegtran icc "-copy;all;-icc;${TESTIMAGES}/test2.icc"
-    testout_rgb_islow2.jpg testout_rgb_islow.jpg ${MD5_JPEG_RGB_ISLOW2})
-
-  if(NOT WITH_12BIT)
-    # CC: RGB->RGB565  SAMP: fullsize  IDCT: islow  ENT: huff
-    add_bittest(djpeg rgb-islow-565 "-dct;int;-rgb565;-dither;none;-bmp"
-      testout_rgb_islow_565.bmp testout_rgb_islow.jpg
-      ${MD5_BMP_RGB_ISLOW_565} cjpeg-${libtype}-rgb-islow)
-
-    # CC: RGB->RGB565 (dithered)  SAMP: fullsize  IDCT: islow  ENT: huff
-    add_bittest(djpeg rgb-islow-565D "-dct;int;-rgb565;-bmp"
-      testout_rgb_islow_565D.bmp testout_rgb_islow.jpg
-      ${MD5_BMP_RGB_ISLOW_565D} cjpeg-${libtype}-rgb-islow)
-  endif()
-
-  # CC: RGB->YCC  SAMP: fullsize/h2v1  FDCT: ifast  ENT: 2-pass huff
-  add_bittest(cjpeg 422-ifast-opt "-sample;2x1;-dct;fast;-opt"
-    testout_422_ifast_opt.jpg ${TESTIMAGES}/testorig.ppm
-    ${MD5_JPEG_422_IFAST_OPT})
-
-  # CC: YCC->RGB  SAMP: fullsize/h2v1 fancy  IDCT: ifast  ENT: huff
-  add_bittest(djpeg 422-ifast "-dct;fast"
-    testout_422_ifast.ppm testout_422_ifast_opt.jpg
-    ${MD5_PPM_422_IFAST} cjpeg-${libtype}-422-ifast-opt)
-
-  # CC: YCC->RGB  SAMP: h2v1 merged  IDCT: ifast  ENT: huff
-  add_bittest(djpeg 422m-ifast "-dct;fast;-nosmooth"
-    testout_422m_ifast.ppm testout_422_ifast_opt.jpg
-    ${MD5_PPM_422M_IFAST} cjpeg-${libtype}-422-ifast-opt)
-
-  if(NOT WITH_12BIT)
-    # CC: YCC->RGB565  SAMP: h2v1 merged  IDCT: ifast  ENT: huff
-    add_bittest(djpeg 422m-ifast-565
-      "-dct;int;-nosmooth;-rgb565;-dither;none;-bmp"
-      testout_422m_ifast_565.bmp testout_422_ifast_opt.jpg
-      ${MD5_BMP_422M_IFAST_565} cjpeg-${libtype}-422-ifast-opt)
-
-    # CC: YCC->RGB565 (dithered)  SAMP: h2v1 merged  IDCT: ifast  ENT: huff
-    add_bittest(djpeg 422m-ifast-565D "-dct;int;-nosmooth;-rgb565;-bmp"
-      testout_422m_ifast_565D.bmp testout_422_ifast_opt.jpg
-      ${MD5_BMP_422M_IFAST_565D} cjpeg-${libtype}-422-ifast-opt)
-  endif()
-
-  # CC: RGB->YCC  SAMP: fullsize/h2v2  FDCT: ifast  ENT: prog huff
-  add_bittest(cjpeg 420-q100-ifast-prog
-    "-sample;2x2;-quality;100;-dct;fast;-prog"
-    testout_420_q100_ifast_prog.jpg ${TESTIMAGES}/testorig.ppm
-    ${MD5_JPEG_420_IFAST_Q100_PROG})
-
-  # CC: YCC->RGB  SAMP: fullsize/h2v2 fancy  IDCT: ifast  ENT: prog huff
-  add_bittest(djpeg 420-q100-ifast-prog "-dct;fast"
-    testout_420_q100_ifast.ppm testout_420_q100_ifast_prog.jpg
-    ${MD5_PPM_420_Q100_IFAST} cjpeg-${libtype}-420-q100-ifast-prog)
-
-  # CC: YCC->RGB  SAMP: h2v2 merged  IDCT: ifast  ENT: prog huff
-  add_bittest(djpeg 420m-q100-ifast-prog "-dct;fast;-nosmooth"
-    testout_420m_q100_ifast.ppm testout_420_q100_ifast_prog.jpg
-    ${MD5_PPM_420M_Q100_IFAST} cjpeg-${libtype}-420-q100-ifast-prog)
-
-  # CC: RGB->Gray  SAMP: fullsize  FDCT: islow  ENT: huff
-  add_bittest(cjpeg gray-islow "-gray;-dct;int"
-    testout_gray_islow.jpg ${TESTIMAGES}/testorig.ppm
-    ${MD5_JPEG_GRAY_ISLOW})
-
-  # CC: Gray->Gray  SAMP: fullsize  IDCT: islow  ENT: huff
-  add_bittest(djpeg gray-islow "-dct;int"
-    testout_gray_islow.ppm testout_gray_islow.jpg
-    ${MD5_PPM_GRAY_ISLOW} cjpeg-${libtype}-gray-islow)
-
-  # CC: Gray->RGB  SAMP: fullsize  IDCT: islow  ENT: huff
-  add_bittest(djpeg gray-islow-rgb "-dct;int;-rgb"
-    testout_gray_islow_rgb.ppm testout_gray_islow.jpg
-    ${MD5_PPM_GRAY_ISLOW_RGB} cjpeg-${libtype}-gray-islow)
-
-  if(NOT WITH_12BIT)
-    # CC: Gray->RGB565  SAMP: fullsize  IDCT: islow  ENT: huff
-    add_bittest(djpeg gray-islow-565 "-dct;int;-rgb565;-dither;none;-bmp"
-      testout_gray_islow_565.bmp testout_gray_islow.jpg
-      ${MD5_BMP_GRAY_ISLOW_565} cjpeg-${libtype}-gray-islow)
-
-    # CC: Gray->RGB565 (dithered)  SAMP: fullsize  IDCT: islow  ENT: huff
-    add_bittest(djpeg gray-islow-565D "-dct;int;-rgb565;-bmp"
-      testout_gray_islow_565D.bmp testout_gray_islow.jpg
-      ${MD5_BMP_GRAY_ISLOW_565D} cjpeg-${libtype}-gray-islow)
-  endif()
-
-  # CC: RGB->YCC  SAMP: fullsize smooth/h2v2 smooth  FDCT: islow
-  # ENT: 2-pass huff
-  add_bittest(cjpeg 420s-ifast-opt "-sample;2x2;-smooth;1;-dct;int;-opt"
-    testout_420s_ifast_opt.jpg ${TESTIMAGES}/testorig.ppm
-    ${MD5_JPEG_420S_IFAST_OPT})
-
-  if(FLOATTEST)
-    # CC: RGB->YCC  SAMP: fullsize/int  FDCT: float  ENT: prog huff
-    add_bittest(cjpeg 3x2-float-prog "-sample;3x2;-dct;float;-prog"
-      testout_3x2_float_prog.jpg ${TESTIMAGES}/testorig.ppm
-      ${MD5_JPEG_3x2_FLOAT_PROG_${FLOATTEST_UC}})
-
-    # CC: YCC->RGB  SAMP: fullsize/int  IDCT: float  ENT: prog huff
-    add_bittest(djpeg 3x2-float-prog "-dct;float"
-      testout_3x2_float.ppm testout_3x2_float_prog.jpg
-      ${MD5_PPM_3x2_FLOAT_${FLOATTEST_UC}} cjpeg-${libtype}-3x2-float-prog)
-  endif()
-
-    # CC: RGB->YCC  SAMP: fullsize/int  FDCT: ifast  ENT: prog huff
-  add_bittest(cjpeg 3x2-ifast-prog "-sample;3x2;-dct;fast;-prog"
-    testout_3x2_ifast_prog.jpg ${TESTIMAGES}/testorig.ppm
-    ${MD5_JPEG_3x2_IFAST_PROG})
-
-  # CC: YCC->RGB  SAMP: fullsize/int  IDCT: ifast  ENT: prog huff
-  add_bittest(djpeg 3x2-ifast-prog "-dct;fast"
-    testout_3x2_ifast.ppm testout_3x2_ifast_prog.jpg
-    ${MD5_PPM_3x2_IFAST} cjpeg-${libtype}-3x2-ifast-prog)
-
-  if(WITH_ARITH_ENC)
-    # CC: YCC->RGB  SAMP: fullsize/h2v2  FDCT: islow  ENT: arith
-    add_bittest(cjpeg 420-islow-ari "-dct;int;-arithmetic"
-      testout_420_islow_ari.jpg ${TESTIMAGES}/testorig.ppm
-      ${MD5_JPEG_420_ISLOW_ARI})
-
-    add_bittest(jpegtran 420-islow-ari "-arithmetic"
-      testout_420_islow_ari2.jpg ${TESTIMAGES}/testimgint.jpg
-      ${MD5_JPEG_420_ISLOW_ARI})
-
-    # CC: YCC->RGB  SAMP: fullsize  FDCT: islow  ENT: prog arith
-    add_bittest(cjpeg 444-islow-progari
-      "-sample;1x1;-dct;int;-prog;-arithmetic"
-      testout_444_islow_progari.jpg ${TESTIMAGES}/testorig.ppm
-      ${MD5_JPEG_444_ISLOW_PROGARI})
-  endif()
-
-  if(WITH_ARITH_DEC)
-    # CC: RGB->YCC  SAMP: h2v2 merged  IDCT: ifast  ENT: arith
-    add_bittest(djpeg 420m-ifast-ari "-fast;-ppm"
-      testout_420m_ifast_ari.ppm ${TESTIMAGES}/testimgari.jpg
-      ${MD5_PPM_420M_IFAST_ARI})
-
-    add_bittest(jpegtran 420-islow ""
-      testout_420_islow.jpg ${TESTIMAGES}/testimgari.jpg
-      ${MD5_JPEG_420_ISLOW})
-  endif()
-
-  # 2/1--   CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 16x16 islow  ENT: huff
-  # 15/8--  CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 15x15 islow  ENT: huff
-  # 13/8--  CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 13x13 islow  ENT: huff
-  # 11/8--  CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 11x11 islow  ENT: huff
-  # 9/8--   CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 9x9 islow  ENT: huff
-  # 7/8--   CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 7x7 islow/14x14 islow
-  #         ENT: huff
-  # 3/4--   CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 6x6 islow/12x12 islow
-  #         ENT: huff
-  # 5/8--   CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 5x5 islow/10x10 islow
-  #         ENT: huff
-  # 1/2--   CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 4x4 islow/8x8 islow
-  #         ENT: huff
-  # 3/8--   CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 3x3 islow/6x6 islow
-  #         ENT: huff
-  # 1/4--   CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 2x2 islow/4x4 islow
-  #         ENT: huff
-  # 1/8--   CC: YCC->RGB  SAMP: h2v2 merged  IDCT: 1x1 islow/2x2 islow
-  #         ENT: huff
-  foreach(scale 2_1 15_8 13_8 11_8 9_8 7_8 3_4 5_8 1_2 3_8 1_4 1_8)
-    string(REGEX REPLACE "_" "/" scalearg ${scale})
-    add_bittest(djpeg 420m-islow-${scale}
-      "-dct;int;-scale;${scalearg};-nosmooth;-ppm"
-      testout_420m_islow_${scale}.ppm ${TESTIMAGES}/${TESTORIG}
-      ${MD5_PPM_420M_ISLOW_${scale}})
-  endforeach()
-
-  if(NOT WITH_12BIT)
-    # CC: YCC->RGB (dithered)  SAMP: h2v2 fancy  IDCT: islow  ENT: huff
-    add_bittest(djpeg 420-islow-256 "-dct;int;-colors;256;-bmp"
-      testout_420_islow_256.bmp ${TESTIMAGES}/${TESTORIG}
-      ${MD5_BMP_420_ISLOW_256})
-
-    # CC: YCC->RGB565  SAMP: h2v2 fancy  IDCT: islow  ENT: huff
-    add_bittest(djpeg 420-islow-565 "-dct;int;-rgb565;-dither;none;-bmp"
-      testout_420_islow_565.bmp ${TESTIMAGES}/${TESTORIG}
-      ${MD5_BMP_420_ISLOW_565})
-
-    # CC: YCC->RGB565 (dithered)  SAMP: h2v2 fancy  IDCT: islow  ENT: huff
-    add_bittest(djpeg 420-islow-565D "-dct;int;-rgb565;-bmp"
-      testout_420_islow_565D.bmp ${TESTIMAGES}/${TESTORIG}
-      ${MD5_BMP_420_ISLOW_565D})
-
-    # CC: YCC->RGB565  SAMP: h2v2 merged  IDCT: islow  ENT: huff
-    add_bittest(djpeg 420m-islow-565
-      "-dct;int;-nosmooth;-rgb565;-dither;none;-bmp"
-      testout_420m_islow_565.bmp ${TESTIMAGES}/${TESTORIG}
-      ${MD5_BMP_420M_ISLOW_565})
-
-    # CC: YCC->RGB565 (dithered)  SAMP: h2v2 merged  IDCT: islow  ENT: huff
-    add_bittest(djpeg 420m-islow-565D "-dct;int;-nosmooth;-rgb565;-bmp"
-      testout_420m_islow_565D.bmp ${TESTIMAGES}/${TESTORIG}
-      ${MD5_BMP_420M_ISLOW_565D})
-  endif()
-
-  # Partial decode tests.  These tests are designed to cover all of the
-  # possible code paths in jpeg_skip_scanlines().
-
-  # Context rows: Yes  Intra-iMCU row: Yes  iMCU row prefetch: No   ENT: huff
-  add_bittest(djpeg 420-islow-skip15_31 "-dct;int;-skip;15,31;-ppm"
-    testout_420_islow_skip15,31.ppm ${TESTIMAGES}/${TESTORIG}
-    ${MD5_PPM_420_ISLOW_SKIP15_31})
-
-  # Context rows: Yes  Intra-iMCU row: No   iMCU row prefetch: Yes  ENT: arith
-  if(WITH_ARITH_DEC)
-    add_bittest(djpeg 420-islow-ari-skip16_139 "-dct;int;-skip;16,139;-ppm"
-      testout_420_islow_ari_skip16,139.ppm ${TESTIMAGES}/testimgari.jpg
-      ${MD5_PPM_420_ISLOW_ARI_SKIP16_139})
-  endif()
-
-  # Context rows: Yes  Intra-iMCU row: No   iMCU row prefetch: No   ENT: prog huff
-  add_test(cjpeg-${libtype}-420-islow-prog
-    cjpeg${suffix} -dct int -prog
-      -outfile testout_420_islow_prog.jpg ${TESTIMAGES}/testorig.ppm)
-  add_bittest(djpeg 420-islow-prog-crop62x62_71_71
-    "-dct;int;-crop;62x62+71+71;-ppm"
-    testout_420_islow_prog_crop62x62,71,71.ppm testout_420_islow_prog.jpg
-    ${MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71} cjpeg-${libtype}-420-islow-prog)
-
-  # Context rows: Yes  Intra-iMCU row: No   iMCU row prefetch: No   ENT: arith
-  if(WITH_ARITH_DEC)
-    add_bittest(djpeg 420-islow-ari-crop53x53_4_4
-      "-dct;int;-crop;53x53+4+4;-ppm"
-      testout_420_islow_ari_crop53x53,4,4.ppm ${TESTIMAGES}/testimgari.jpg
-      ${MD5_PPM_420_ISLOW_ARI_CROP53x53_4_4})
-  endif()
-
-  # Context rows: No   Intra-iMCU row: Yes  ENT: huff
-  add_test(cjpeg-${libtype}-444-islow
-    cjpeg${suffix} -dct int -sample 1x1
-      -outfile testout_444_islow.jpg ${TESTIMAGES}/testorig.ppm)
-  add_bittest(djpeg 444-islow-skip1_6 "-dct;int;-skip;1,6;-ppm"
-    testout_444_islow_skip1,6.ppm testout_444_islow.jpg
-    ${MD5_PPM_444_ISLOW_SKIP1_6} cjpeg-${libtype}-444-islow)
-
-  # Context rows: No   Intra-iMCU row: No   ENT: prog huff
-  add_test(cjpeg-${libtype}-444-islow-prog
-    cjpeg${suffix} -dct int -prog -sample 1x1
-      -outfile testout_444_islow_prog.jpg ${TESTIMAGES}/testorig.ppm)
-  add_bittest(djpeg 444-islow-prog-crop98x98_13_13
-    "-dct;int;-crop;98x98+13+13;-ppm"
-    testout_444_islow_prog_crop98x98,13,13.ppm testout_444_islow_prog.jpg
-    ${MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13} cjpeg-${libtype}-444-islow-prog)
-
-  # Context rows: No   Intra-iMCU row: No   ENT: arith
-  if(WITH_ARITH_ENC)
-    add_test(cjpeg-${libtype}-444-islow-ari
-      cjpeg${suffix} -dct int -arithmetic -sample 1x1
-        -outfile testout_444_islow_ari.jpg ${TESTIMAGES}/testorig.ppm)
-    if(WITH_ARITH_DEC)
-      add_bittest(djpeg 444-islow-ari-crop37x37_0_0
-        "-dct;int;-crop;37x37+0+0;-ppm"
-        testout_444_islow_ari_crop37x37,0,0.ppm testout_444_islow_ari.jpg
-        ${MD5_PPM_444_ISLOW_ARI_CROP37x37_0_0} cjpeg-${libtype}-444-islow-ari)
-    endif()
-  endif()
-
-  add_bittest(jpegtran crop "-crop;120x90+20+50;-transpose;-perfect"
-    testout_crop.jpg ${TESTIMAGES}/${TESTORIG}
-    ${MD5_JPEG_CROP})
-
-endforeach()
-
-add_custom_target(testclean COMMAND ${CMAKE_COMMAND} -P
-  ${CMAKE_CURRENT_SOURCE_DIR}/cmakescripts/testclean.cmake)
-
-if(WITH_TURBOJPEG)
-  configure_file(tjbenchtest.in tjbenchtest @ONLY)
-  configure_file(tjexampletest.in tjexampletest @ONLY)
-  if(WIN32)
-    set(BASH bash)
-  endif()
-  if(WITH_JAVA)
-    configure_file(tjbenchtest.java.in tjbenchtest.java @ONLY)
-    configure_file(tjexampletest.java.in tjexampletest.java @ONLY)
-    add_custom_target(tjtest
-      COMMAND echo tjbenchtest
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest
-      COMMAND echo tjbenchtest -alloc
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest -alloc
-      COMMAND echo tjbenchtest -yuv
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest -yuv
-      COMMAND echo tjbenchtest -yuv -alloc
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest -yuv -alloc
-      COMMAND echo tjbenchtest -progressive
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest -progressive
-      COMMAND echo tjexampletest
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjexampletest
-      COMMAND echo tjbenchtest.java
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest.java
-      COMMAND echo tjbenchtest.java -yuv
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest.java -yuv
-      COMMAND echo tjbenchtest.java -progressive
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest.java -progressive
-      COMMAND echo tjexampletest.java
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjexampletest.java
-      DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest
-        ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest.java
-        ${CMAKE_CURRENT_BINARY_DIR}/tjexampletest)
-  else()
-    add_custom_target(tjtest
-      COMMAND echo tjbenchtest
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest
-      COMMAND echo tjbenchtest -alloc
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest -alloc
-      COMMAND echo tjbenchtest -yuv
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest -yuv
-      COMMAND echo tjbenchtest -yuv -alloc
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest -yuv -alloc
-      COMMAND echo tjexampletest
-      COMMAND ${BASH} ${CMAKE_CURRENT_BINARY_DIR}/tjexampletest
-      DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/tjbenchtest)
-  endif()
-endif()
-
-
-###############################################################################
-# INSTALLATION
-###############################################################################
-
-if(WIN32)
-  set(EXE ".exe")
-endif()
-
-if(WITH_TURBOJPEG)
-  if(ENABLE_SHARED)
-    install(TARGETS turbojpeg tjbench
-      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-      LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-  endif()
-  if(ENABLE_STATIC)
-    install(TARGETS turbojpeg-static ARCHIVE
-      DESTINATION ${CMAKE_INSTALL_LIBDIR})
-    if(NOT ENABLE_SHARED)
-      install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/tjbench-static${EXE}
-        DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME tjbench${EXE})
-    endif()
-  endif()
-  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/turbojpeg.h
-    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-endif()
-
-if(ENABLE_STATIC)
-  install(TARGETS jpeg-static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
-  if(NOT ENABLE_SHARED)
-    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/cjpeg-static${EXE}
-      DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME cjpeg${EXE})
-    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/djpeg-static${EXE}
-      DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME djpeg${EXE})
-    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/jpegtran-static${EXE}
-      DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME jpegtran${EXE})
-  endif()
-endif()
-
-install(TARGETS rdjpgcom wrjpgcom RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-
-install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/README.ijg
-  ${CMAKE_CURRENT_SOURCE_DIR}/README.md ${CMAKE_CURRENT_SOURCE_DIR}/example.txt
-  ${CMAKE_CURRENT_SOURCE_DIR}/tjexample.c
-  ${CMAKE_CURRENT_SOURCE_DIR}/libjpeg.txt
-  ${CMAKE_CURRENT_SOURCE_DIR}/structure.txt
-  ${CMAKE_CURRENT_SOURCE_DIR}/usage.txt ${CMAKE_CURRENT_SOURCE_DIR}/wizard.txt
-  ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md DESTINATION ${CMAKE_INSTALL_DOCDIR})
-if(WITH_JAVA)
-  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/java/TJExample.java
-    DESTINATION ${CMAKE_INSTALL_DOCDIR})
-endif()
-
-if(UNIX OR MINGW)
-  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cjpeg.1
-    ${CMAKE_CURRENT_SOURCE_DIR}/djpeg.1 ${CMAKE_CURRENT_SOURCE_DIR}/jpegtran.1
-    ${CMAKE_CURRENT_SOURCE_DIR}/rdjpgcom.1
-    ${CMAKE_CURRENT_SOURCE_DIR}/wrjpgcom.1
-    DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
-  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libjpeg.pc
-    ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libturbojpeg.pc
-    DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
-endif()
-
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jconfig.h
-  ${CMAKE_CURRENT_SOURCE_DIR}/jerror.h ${CMAKE_CURRENT_SOURCE_DIR}/jmorecfg.h
-  ${CMAKE_CURRENT_SOURCE_DIR}/jpeglib.h
-  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-
-include(cmakescripts/BuildPackages.cmake)
-
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmakescripts/cmake_uninstall.cmake.in"
-  "cmake_uninstall.cmake" IMMEDIATE @ONLY)
-
-add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P cmake_uninstall.cmake)
diff --git a/src/third_party/libjpeg-turbo/ChangeLog.md b/src/third_party/libjpeg-turbo/ChangeLog.md
index 57bcf1d..ca5208b 100644
--- a/src/third_party/libjpeg-turbo/ChangeLog.md
+++ b/src/third_party/libjpeg-turbo/ChangeLog.md
@@ -1,3 +1,430 @@
+2.1.1
+=====
+
+### Significant changes relative to 2.1.0
+
+1. Fixed a regression introduced in 2.1.0 that caused build failures with
+non-GCC-compatible compilers for Un*x/Arm platforms.
+
+2. Fixed a regression introduced by 2.1 beta1[13] that prevented the Arm 32-bit
+(AArch32) Neon SIMD extensions from building unless the C compiler flags
+included `-mfloat-abi=softfp` or `-mfloat-abi=hard`.
+
+3. Fixed an issue in the AArch32 Neon SIMD Huffman encoder whereby reliance on
+undefined C compiler behavior led to crashes ("SIGBUS: illegal alignment") on
+Android systems when running AArch32/Thumb builds of libjpeg-turbo built with
+recent versions of Clang.
+
+
+2.1.0
+=====
+
+### Significant changes relative to 2.1 beta1
+
+1. Fixed a regression introduced by 2.1 beta1[6(b)] whereby attempting to
+decompress certain progressive JPEG images with one or more component planes of
+width 8 or less caused a buffer overrun.
+
+2. Fixed a regression introduced by 2.1 beta1[6(b)] whereby attempting to
+decompress a specially-crafted malformed progressive JPEG image caused the
+block smoothing algorithm to read from uninitialized memory.
+
+3. Fixed an issue in the Arm Neon SIMD Huffman encoders that caused the
+encoders to generate incorrect results when using the Clang compiler with
+Visual Studio.
+
+4. Fixed a floating point exception (CVE-2021-20205) that occurred when
+attempting to compress a specially-crafted malformed GIF image with a specified
+image width of 0 using cjpeg.
+
+5. Fixed a regression introduced by 2.0 beta1[15] whereby attempting to
+generate a progressive JPEG image on an SSE2-capable CPU using a scan script
+containing one or more scans with lengths divisible by 32 and non-zero
+successive approximation low bit positions would, under certain circumstances,
+result in an error ("Missing Huffman code table entry") and an invalid JPEG
+image.
+
+6. Introduced a new flag (`TJFLAG_LIMITSCANS` in the TurboJPEG C API and
+`TJ.FLAG_LIMIT_SCANS` in the TurboJPEG Java API) and a corresponding TJBench
+command-line argument (`-limitscans`) that causes the TurboJPEG decompression
+and transform functions/operations to return/throw an error if a progressive
+JPEG image contains an unreasonably large number of scans.  This allows
+applications that use the TurboJPEG API to guard against an exploit of the
+progressive JPEG format described in the report
+["Two Issues with the JPEG Standard"](https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf).
+
+7. The PPM reader now throws an error, rather than segfaulting (due to a buffer
+overrun) or generating incorrect pixels, if an application attempts to use the
+`tjLoadImage()` function to load a 16-bit binary PPM file (a binary PPM file
+with a maximum value greater than 255) into a grayscale image buffer or to load
+a 16-bit binary PGM file into an RGB image buffer.
+
+8. Fixed an issue in the PPM reader that caused incorrect pixels to be
+generated when using the `tjLoadImage()` function to load a 16-bit binary PPM
+file into an extended RGB image buffer.
+
+9. Fixed an issue whereby, if a JPEG buffer was automatically re-allocated by
+one of the TurboJPEG compression or transform functions and an error
+subsequently occurred during compression or transformation, the JPEG buffer
+pointer passed by the application was not updated when the function returned.
+
+
+2.0.90 (2.1 beta1)
+==================
+
+### Significant changes relative to 2.0.6:
+
+1. The build system, x86-64 SIMD extensions, and accelerated Huffman codec now
+support the x32 ABI on Linux, which allows for using x86-64 instructions with
+32-bit pointers.  The x32 ABI is generally enabled by adding `-mx32` to the
+compiler flags.
+
+     Caveats:
+     - CMake 3.9.0 or later is required in order for the build system to
+automatically detect an x32 build.
+     - Java does not support the x32 ABI, and thus the TurboJPEG Java API will
+automatically be disabled with x32 builds.
+
+2. Added Loongson MMI SIMD implementations of the RGB-to-grayscale, 4:2:2 fancy
+chroma upsampling, 4:2:2 and 4:2:0 merged chroma upsampling/color conversion,
+and fast integer DCT/IDCT algorithms.  Relative to libjpeg-turbo 2.0.x, this
+speeds up:
+
+     - the compression of RGB source images into grayscale JPEG images by
+approximately 20%
+     - the decompression of 4:2:2 JPEG images by approximately 40-60% when
+using fancy upsampling
+     - the decompression of 4:2:2 and 4:2:0 JPEG images by approximately
+15-20% when using merged upsampling
+     - the compression of RGB source images by approximately 30-45% when using
+the fast integer DCT
+     - the decompression of JPEG images into RGB destination images by
+approximately 2x when using the fast integer IDCT
+
+    The overall decompression speedup for RGB images is now approximately
+2.3-3.7x (compared to 2-3.5x with libjpeg-turbo 2.0.x.)
+
+3. 32-bit (Armv7 or Armv7s) iOS builds of libjpeg-turbo are no longer
+supported, and the libjpeg-turbo build system can no longer be used to package
+such builds.  32-bit iOS apps cannot run in iOS 11 and later, and the App Store
+no longer allows them.
+
+4. 32-bit (i386) OS X/macOS builds of libjpeg-turbo are no longer supported,
+and the libjpeg-turbo build system can no longer be used to package such
+builds.  32-bit Mac applications cannot run in macOS 10.15 "Catalina" and
+later, and the App Store no longer allows them.
+
+5. The SSE2 (x86 SIMD) and C Huffman encoding algorithms have been
+significantly optimized, resulting in a measured average overall compression
+speedup of 12-28% for 64-bit code and 22-52% for 32-bit code on various Intel
+and AMD CPUs, as well as a measured average overall compression speedup of
+0-23% on platforms that do not have a SIMD-accelerated Huffman encoding
+implementation.
+
+6. The block smoothing algorithm that is applied by default when decompressing
+progressive Huffman-encoded JPEG images has been improved in the following
+ways:
+
+     - The algorithm is now more fault-tolerant.  Previously, if a particular
+scan was incomplete, then the smoothing parameters for the incomplete scan
+would be applied to the entire output image, including the parts of the image
+that were generated by the prior (complete) scan.  Visually, this had the
+effect of removing block smoothing from lower-frequency scans if they were
+followed by an incomplete higher-frequency scan.  libjpeg-turbo now applies
+block smoothing parameters to each iMCU row based on which scan generated the
+pixels in that row, rather than always using the block smoothing parameters for
+the most recent scan.
+     - When applying block smoothing to DC scans, a Gaussian-like kernel with a
+5x5 window is used to reduce the "blocky" appearance.
+
+7. Added SIMD acceleration for progressive Huffman encoding on Arm platforms.
+This speeds up the compression of full-color progressive JPEGs by about 30-40%
+on average (relative to libjpeg-turbo 2.0.x) when using modern Arm CPUs.
+
+8. Added configure-time and run-time auto-detection of Loongson MMI SIMD
+instructions, so that the Loongson MMI SIMD extensions can be included in any
+MIPS64 libjpeg-turbo build.
+
+9. Added fault tolerance features to djpeg and jpegtran, mainly to demonstrate
+methods by which applications can guard against the exploits of the JPEG format
+described in the report
+["Two Issues with the JPEG Standard"](https://libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf).
+
+     - Both programs now accept a `-maxscans` argument, which can be used to
+limit the number of allowable scans in the input file.
+     - Both programs now accept a `-strict` argument, which can be used to
+treat all warnings as fatal.
+
+10. CMake package config files are now included for both the libjpeg and
+TurboJPEG API libraries.  This facilitates using libjpeg-turbo with CMake's
+`find_package()` function.  For example:
+
+        find_package(libjpeg-turbo CONFIG REQUIRED)
+
+        add_executable(libjpeg_program libjpeg_program.c)
+        target_link_libraries(libjpeg_program PUBLIC libjpeg-turbo::jpeg)
+
+        add_executable(libjpeg_program_static libjpeg_program.c)
+        target_link_libraries(libjpeg_program_static PUBLIC
+          libjpeg-turbo::jpeg-static)
+
+        add_executable(turbojpeg_program turbojpeg_program.c)
+        target_link_libraries(turbojpeg_program PUBLIC
+          libjpeg-turbo::turbojpeg)
+
+        add_executable(turbojpeg_program_static turbojpeg_program.c)
+        target_link_libraries(turbojpeg_program_static PUBLIC
+          libjpeg-turbo::turbojpeg-static)
+
+11. Since the Unisys LZW patent has long expired, cjpeg and djpeg can now
+read/write both LZW-compressed and uncompressed GIF files (feature ported from
+jpeg-6a and jpeg-9d.)
+
+12. jpegtran now includes the `-wipe` and `-drop` options from jpeg-9a and
+jpeg-9d, as well as the ability to expand the image size using the `-crop`
+option.  Refer to jpegtran.1 or usage.txt for more details.
+
+13. Added a complete intrinsics implementation of the Arm Neon SIMD extensions,
+thus providing SIMD acceleration on Arm platforms for all of the algorithms
+that are SIMD-accelerated on x86 platforms.  This new implementation is
+significantly faster in some cases than the old GAS implementation--
+depending on the algorithms used, the type of CPU core, and the compiler.  GCC,
+as of this writing, does not provide a full or optimal set of Neon intrinsics,
+so for performance reasons, the default when building libjpeg-turbo with GCC is
+to continue using the GAS implementation of the following algorithms:
+
+     - 32-bit RGB-to-YCbCr color conversion
+     - 32-bit fast and accurate inverse DCT
+     - 64-bit RGB-to-YCbCr and YCbCr-to-RGB color conversion
+     - 64-bit accurate forward and inverse DCT
+     - 64-bit Huffman encoding
+
+    A new CMake variable (`NEON_INTRINSICS`) can be used to override this
+default.
+
+    Since the new intrinsics implementation includes SIMD acceleration
+for merged upsampling/color conversion, 1.5.1[5] is no longer necessary and has
+been reverted.
+
+14. The Arm Neon SIMD extensions can now be built using Visual Studio.
+
+15. The build system can now be used to generate a universal x86-64 + Armv8
+libjpeg-turbo SDK package for both iOS and macOS.
+
+
+2.0.6
+=====
+
+### Significant changes relative to 2.0.5:
+
+1. Fixed "using JNI after critical get" errors that occurred on Android
+platforms when using any of the YUV encoding/compression/decompression/decoding
+methods in the TurboJPEG Java API.
+
+2. Fixed or worked around multiple issues with `jpeg_skip_scanlines()`:
+
+     - Fixed segfaults or "Corrupt JPEG data: premature end of data segment"
+errors in `jpeg_skip_scanlines()` that occurred when decompressing 4:2:2 or
+4:2:0 JPEG images using merged (non-fancy) upsampling/color conversion (that
+is, when setting `cinfo.do_fancy_upsampling` to `FALSE`.)  2.0.0[6] was a
+similar fix, but it did not cover all cases.
+     - `jpeg_skip_scanlines()` now throws an error if two-pass color
+quantization is enabled.  Two-pass color quantization never worked properly
+with `jpeg_skip_scanlines()`, and the issues could not readily be fixed.
+     - Fixed an issue whereby `jpeg_skip_scanlines()` always returned 0 when
+skipping past the end of an image.
+
+3. The Arm 64-bit (Armv8) Neon SIMD extensions can now be built using MinGW
+toolchains targetting Arm64 (AArch64) Windows binaries.
+
+4. Fixed unexpected visual artifacts that occurred when using
+`jpeg_crop_scanline()` and interblock smoothing while decompressing only the DC
+scan of a progressive JPEG image.
+
+5. Fixed an issue whereby libjpeg-turbo would not build if 12-bit-per-component
+JPEG support (`WITH_12BIT`) was enabled along with libjpeg v7 or libjpeg v8
+API/ABI emulation (`WITH_JPEG7` or `WITH_JPEG8`.)
+
+
+2.0.5
+=====
+
+### Significant changes relative to 2.0.4:
+
+1. Worked around issues in the MIPS DSPr2 SIMD extensions that caused failures
+in the libjpeg-turbo regression tests.  Specifically, the
+`jsimd_h2v1_downsample_dspr2()` and `jsimd_h2v2_downsample_dspr2()` functions
+in the MIPS DSPr2 SIMD extensions are now disabled until/unless they can be
+fixed, and other functions that are incompatible with big endian MIPS CPUs are
+disabled when building libjpeg-turbo for such CPUs.
+
+2. Fixed an oversight in the `TJCompressor.compress(int)` method in the
+TurboJPEG Java API that caused an error ("java.lang.IllegalStateException: No
+source image is associated with this instance") when attempting to use that
+method to compress a YUV image.
+
+3. Fixed an issue (CVE-2020-13790) in the PPM reader that caused a buffer
+overrun in cjpeg, TJBench, or the `tjLoadImage()` function if one of the values
+in a binary PPM/PGM input file exceeded the maximum value defined in the file's
+header and that maximum value was less than 255.  libjpeg-turbo 1.5.0 already
+included a similar fix for binary PPM/PGM files with maximum values greater
+than 255.
+
+4. The TurboJPEG API library's global error handler, which is used in functions
+such as `tjBufSize()` and `tjLoadImage()` that do not require a TurboJPEG
+instance handle, is now thread-safe on platforms that support thread-local
+storage.
+
+
+2.0.4
+=====
+
+### Significant changes relative to 2.0.3:
+
+1. Fixed a regression in the Windows packaging system (introduced by
+2.0 beta1[2]) whereby, if both the 64-bit libjpeg-turbo SDK for GCC and the
+64-bit libjpeg-turbo SDK for Visual C++ were installed on the same system, only
+one of them could be uninstalled.
+
+2. Fixed a signed integer overflow and subsequent segfault that occurred when
+attempting to decompress images with more than 715827882 pixels using the
+64-bit C version of TJBench.
+
+3. Fixed out-of-bounds write in `tjDecompressToYUV2()` and
+`tjDecompressToYUVPlanes()` (sometimes manifesting as a double free) that
+occurred when attempting to decompress grayscale JPEG images that were
+compressed with a sampling factor other than 1 (for instance, with
+`cjpeg -grayscale -sample 2x2`).
+
+4. Fixed a regression introduced by 2.0.2[5] that caused the TurboJPEG API to
+incorrectly identify some JPEG images with unusual sampling factors as 4:4:4
+JPEG images.  This was known to cause a buffer overflow when attempting to
+decompress some such images using `tjDecompressToYUV2()` or
+`tjDecompressToYUVPlanes()`.
+
+5. Fixed an issue (CVE-2020-17541), detected by ASan, whereby attempting to
+losslessly transform a specially-crafted malformed JPEG image containing an
+extremely-high-frequency coefficient block (junk image data that could never be
+generated by a legitimate JPEG compressor) could cause the Huffman encoder's
+local buffer to be overrun. (Refer to 1.4.0[9] and 1.4beta1[15].)  Given that
+the buffer overrun was fully contained within the stack and did not cause a
+segfault or other user-visible errant behavior, and given that the lossless
+transformer (unlike the decompressor) is not generally exposed to arbitrary
+data exploits, this issue did not likely pose a security risk.
+
+6. The Arm 64-bit (Armv8) Neon SIMD assembly code now stores constants in a
+separate read-only data section rather than in the text section, to support
+execute-only memory layouts.
+
+
+2.0.3
+=====
+
+### Significant changes relative to 2.0.2:
+
+1. Fixed "using JNI after critical get" errors that occurred on Android
+platforms when passing invalid arguments to certain methods in the TurboJPEG
+Java API.
+
+2. Fixed a regression in the SIMD feature detection code, introduced by
+the AVX2 SIMD extensions (2.0 beta1[1]), that was known to cause an illegal
+instruction exception, in rare cases, on CPUs that lack support for CPUID leaf
+07H (or on which the maximum CPUID leaf has been limited by way of a BIOS
+setting.)
+
+3. The 4:4:0 (h1v2) fancy (smooth) chroma upsampling algorithm in the
+decompressor now uses a similar bias pattern to that of the 4:2:2 (h2v1) fancy
+chroma upsampling algorithm, rounding up or down the upsampled result for
+alternate pixels rather than always rounding down.  This ensures that,
+regardless of whether a 4:2:2 JPEG image is rotated or transposed prior to
+decompression (in the frequency domain) or after decompression (in the spatial
+domain), the final image will be similar.
+
+4. Fixed an integer overflow and subsequent segfault that occurred when
+attempting to compress or decompress images with more than 1 billion pixels
+using the TurboJPEG API.
+
+5. Fixed a regression introduced by 2.0 beta1[15] whereby attempting to
+generate a progressive JPEG image on an SSE2-capable CPU using a scan script
+containing one or more scans with lengths divisible by 16 would result in an
+error ("Missing Huffman code table entry") and an invalid JPEG image.
+
+6. Fixed an issue whereby `tjDecodeYUV()` and `tjDecodeYUVPlanes()` would throw
+an error ("Invalid progressive parameters") or a warning ("Inconsistent
+progression sequence") if passed a TurboJPEG instance that was previously used
+to decompress a progressive JPEG image.
+
+
+2.0.2
+=====
+
+### Significant changes relative to 2.0.1:
+
+1. Fixed a regression introduced by 2.0.1[5] that prevented a runtime search
+path (rpath) from being embedded in the libjpeg-turbo shared libraries and
+executables for macOS and iOS.  This caused a fatal error of the form
+"dyld: Library not loaded" when attempting to use one of the executables,
+unless `DYLD_LIBRARY_PATH` was explicitly set to the location of the
+libjpeg-turbo shared libraries.
+
+2. Fixed an integer overflow and subsequent segfault (CVE-2018-20330) that
+occurred when attempting to load a BMP file with more than 1 billion pixels
+using the `tjLoadImage()` function.
+
+3. Fixed a buffer overrun (CVE-2018-19664) that occurred when attempting to
+decompress a specially-crafted malformed JPEG image to a 256-color BMP using
+djpeg.
+
+4. Fixed a floating point exception that occurred when attempting to
+decompress a specially-crafted malformed JPEG image with a specified image
+width or height of 0 using the C version of TJBench.
+
+5. The TurboJPEG API will now decompress 4:4:4 JPEG images with 2x1, 1x2, 3x1,
+or 1x3 luminance and chrominance sampling factors.  This is a non-standard way
+of specifying 1x subsampling (normally 4:4:4 JPEGs have 1x1 luminance and
+chrominance sampling factors), but the JPEG format and the libjpeg API both
+allow it.
+
+6. Fixed a regression introduced by 2.0 beta1[7] that caused djpeg to generate
+incorrect PPM images when used with the `-colors` option.
+
+7. Fixed an issue whereby a static build of libjpeg-turbo (a build in which
+`ENABLE_SHARED` is `0`) could not be installed using the Visual Studio IDE.
+
+8. Fixed a severe performance issue in the Loongson MMI SIMD extensions that
+occurred when compressing RGB images whose image rows were not 64-bit-aligned.
+
+
+2.0.1
+=====
+
+### Significant changes relative to 2.0.0:
+
+1. Fixed a regression introduced with the new CMake-based Un*x build system,
+whereby jconfig.h could cause compiler warnings of the form
+`"HAVE_*_H" redefined` if it was included by downstream Autotools-based
+projects that used `AC_CHECK_HEADERS()` to check for the existence of locale.h,
+stddef.h, or stdlib.h.
+
+2. The `jsimd_quantize_float_dspr2()` and `jsimd_convsamp_float_dspr2()`
+functions in the MIPS DSPr2 SIMD extensions are now disabled at compile time
+if the soft float ABI is enabled.  Those functions use instructions that are
+incompatible with the soft float ABI.
+
+3. Fixed a regression in the SIMD feature detection code, introduced by
+the AVX2 SIMD extensions (2.0 beta1[1]), that caused libjpeg-turbo to crash on
+Windows 7 if Service Pack 1 was not installed.
+
+4. Fixed out-of-bounds read in cjpeg that occurred when attempting to compress
+a specially-crafted malformed color-index (8-bit-per-sample) Targa file in
+which some of the samples (color indices) exceeded the bounds of the Targa
+file's color table.
+
+5. Fixed an issue whereby installing a fully static build of libjpeg-turbo
+(a build in which `CFLAGS` contains `-static` and `ENABLE_SHARED` is `0`) would
+fail with "No valid ELF RPATH or RUNPATH entry exists in the file."
+
+
 2.0.0
 =====
 
@@ -11,6 +438,54 @@
 `tjDecompressToYUVPlanes()`, `tjDecompressToYUV2()`, or the equivalent Java
 methods.
 
+2. Fixed an issue (CVE-2018-11813) whereby a specially-crafted malformed input
+file (specifically, a file with a valid Targa header but incomplete pixel data)
+would cause cjpeg to generate a JPEG file that was potentially thousands of
+times larger than the input file.  The Targa reader in cjpeg was not properly
+detecting that the end of the input file had been reached prematurely, so after
+all valid pixels had been read from the input, the reader injected dummy pixels
+with values of 255 into the JPEG compressor until the number of pixels
+specified in the Targa header had been compressed.  The Targa reader in cjpeg
+now behaves like the PPM reader and aborts compression if the end of the input
+file is reached prematurely.  Because this issue only affected cjpeg and not
+the underlying library, and because it did not involve any out-of-bounds reads
+or other exploitable behaviors, it was not believed to represent a security
+threat.
+
+3. Fixed an issue whereby the `tjLoadImage()` and `tjSaveImage()` functions
+would produce a "Bogus message code" error message if the underlying bitmap and
+PPM readers/writers threw an error that was specific to the readers/writers
+(as opposed to a general libjpeg API error.)
+
+4. Fixed an issue (CVE-2018-1152) whereby a specially-crafted malformed BMP
+file, one in which the header specified an image width of 1073741824 pixels,
+would trigger a floating point exception (division by zero) in the
+`tjLoadImage()` function when attempting to load the BMP file into a
+4-component image buffer.
+
+5. Fixed an issue whereby certain combinations of calls to
+`jpeg_skip_scanlines()` and `jpeg_read_scanlines()` could trigger an infinite
+loop when decompressing progressive JPEG images that use vertical chroma
+subsampling (for instance, 4:2:0 or 4:4:0.)
+
+6. Fixed a segfault in `jpeg_skip_scanlines()` that occurred when decompressing
+a 4:2:2 or 4:2:0 JPEG image using the merged (non-fancy) upsampling algorithms
+(that is, when setting `cinfo.do_fancy_upsampling` to `FALSE`.)
+
+7. The new CMake-based build system will now disable the MIPS DSPr2 SIMD
+extensions if it detects that the compiler does not support DSPr2 instructions.
+
+8. Fixed out-of-bounds read in cjpeg (CVE-2018-14498) that occurred when
+attempting to compress a specially-crafted malformed color-index
+(8-bit-per-sample) BMP file in which some of the samples (color indices)
+exceeded the bounds of the BMP file's color table.
+
+9. Fixed a signed integer overflow in the progressive Huffman decoder, detected
+by the Clang and GCC undefined behavior sanitizers, that could be triggered by
+attempting to decompress a specially-crafted malformed JPEG image.  This issue
+did not pose a security threat, but removing the warning made it easier to
+detect actual security issues, should they arise in the future.
+
 
 1.5.90 (2.0 beta1)
 ==================
@@ -19,7 +494,7 @@
 
 1. Added AVX2 SIMD implementations of the colorspace conversion, chroma
 downsampling and upsampling, integer quantization and sample conversion, and
-slow integer DCT/IDCT algorithms.  When using the slow integer DCT/IDCT
+accurate integer DCT/IDCT algorithms.  When using the accurate integer DCT/IDCT
 algorithms on AVX2-equipped CPUs, the compression of RGB images is
 approximately 13-36% (avg. 22%) faster (relative to libjpeg-turbo 1.5.x) with
 64-bit code and 11-21% (avg. 17%) faster with 32-bit code, and the
@@ -123,16 +598,16 @@
 now produces bitwise-identical results to the unmerged algorithms.
 
 12. The SIMD function symbols for x86[-64]/ELF, MIPS/ELF, macOS/x86[-64] (if
-libjpeg-turbo is built with YASM), and iOS/ARM[64] builds are now private.
+libjpeg-turbo is built with YASM), and iOS/Arm[64] builds are now private.
 This prevents those symbols from being exposed in applications or shared
 libraries that link statically with libjpeg-turbo.
 
 13. Added Loongson MMI SIMD implementations of the RGB-to-YCbCr and
 YCbCr-to-RGB colorspace conversion, 4:2:0 chroma downsampling, 4:2:0 fancy
-chroma upsampling, integer quantization, and slow integer DCT/IDCT algorithms.
-When using the slow integer DCT/IDCT, this speeds up the compression of RGB
-images by approximately 70-100% and the decompression of RGB images by
-approximately 2-3.5x.
+chroma upsampling, integer quantization, and accurate integer DCT/IDCT
+algorithms.  When using the accurate integer DCT/IDCT, this speeds up the
+compression of RGB images by approximately 70-100% and the decompression of RGB
+images by approximately 2-3.5x.
 
 14. Fixed a build error when building with older MinGW releases (regression
 caused by 1.5.1[7].)
@@ -163,8 +638,8 @@
 output format other than PPM/PGM, GIF, or Targa is selected along with the
 `-crop` option.
 
-4. Fixed an issue whereby `jpeg_skip_scanlines()` would segfault if color
-quantization was enabled.
+4. Fixed an issue (CVE-2017-15232) whereby `jpeg_skip_scanlines()` would
+segfault if color quantization was enabled.
 
 5. TJBench (both C and Java versions) will now display usage information if any
 command-line argument is unrecognized.  This prevents the program from silently
@@ -182,9 +657,9 @@
 `jpeg_consume_input()` would return `JPEG_SUSPENDED` rather than
 `JPEG_REACHED_EOI`.
 
-9. `jpeg_crop_scanlines()` now works correctly when decompressing grayscale
-JPEG images that were compressed with a sampling factor other than 1 (for
-instance, with `cjpeg -grayscale -sample 2x2`).
+9. `jpeg_crop_scanline()` now works correctly when decompressing grayscale JPEG
+images that were compressed with a sampling factor other than 1 (for instance,
+with `cjpeg -grayscale -sample 2x2`).
 
 
 1.5.2
@@ -208,7 +683,7 @@
 5. Fixed build and runtime errors on Windows that occurred when building
 libjpeg-turbo with libjpeg v7 API/ABI emulation and the in-memory
 source/destination managers.  Due to an oversight, the `jpeg_skip_scanlines()`
-and `jpeg_crop_scanlines()` functions were not being included in jpeg7.dll when
+and `jpeg_crop_scanline()` functions were not being included in jpeg7.dll when
 libjpeg-turbo was built with `-DWITH_JPEG7=1` and `-DWITH_MEMSRCDST=1`.
 
 6. Fixed "Bogus virtual array access" error that occurred when using the
@@ -319,8 +794,8 @@
 2x2 luminance sampling factors and 2x1 or 1x2 chrominance sampling factors.
 This is a non-standard way of specifying 2x subsampling (normally 4:2:2 JPEGs
 have 2x1 luminance and 1x1 chrominance sampling factors, and 4:4:0 JPEGs have
-1x2 luminance and 1x1 chrominance sampling factors), but the JPEG specification
-and the libjpeg API both allow it.
+1x2 luminance and 1x1 chrominance sampling factors), but the JPEG format and
+the libjpeg API both allow it.
 
 7. Fixed an unsigned integer overflow in the libjpeg memory manager, detected
 by the Clang undefined behavior sanitizer, that could be triggered by
@@ -365,10 +840,10 @@
 
 3. Fixed a couple of issues in the PPM reader that would cause buffer overruns
 in cjpeg if one of the values in a binary PPM/PGM input file exceeded the
-maximum value defined in the file's header.  libjpeg-turbo 1.4.2 already
-included a similar fix for ASCII PPM/PGM files.  Note that these issues were
-not security bugs, since they were confined to the cjpeg program and did not
-affect any of the libjpeg-turbo libraries.
+maximum value defined in the file's header and that maximum value was greater
+than 255.  libjpeg-turbo 1.4.2 already included a similar fix for ASCII PPM/PGM
+files.  Note that these issues were not security bugs, since they were confined
+to the cjpeg program and did not affect any of the libjpeg-turbo libraries.
 
 4. Fixed an issue whereby attempting to decompress a JPEG file with a corrupt
 header using the `tjDecompressToYUV2()` function would cause the function to
@@ -464,8 +939,8 @@
 disabled by setting the `JSIMD_NOHUFFENC` environment variable to `1`.
 
 13. Added ARM 64-bit (ARMv8) NEON SIMD implementations of the commonly-used
-compression algorithms (including the slow integer forward DCT and h2v2 & h2v1
-downsampling algorithms, which are not accelerated in the 32-bit NEON
+compression algorithms (including the accurate integer forward DCT and h2v2 &
+h2v1 downsampling algorithms, which are not accelerated in the 32-bit NEON
 implementation.)  This speeds up the compression of full-color JPEGs by about
 75% on average on a Cavium ThunderX processor and by about 2-2.5x on average on
 Cortex-A53 and Cortex-A57 cores.
@@ -596,8 +1071,8 @@
 
 7. Fixed an extremely rare bug in the Huffman encoder that caused 64-bit
 builds of libjpeg-turbo to incorrectly encode a few specific test images when
-quality=98, an optimized Huffman table, and the slow integer forward DCT were
-used.
+quality=98, an optimized Huffman table, and the accurate integer forward DCT
+were used.
 
 8. The Windows (CMake) build system now supports building only static or only
 shared libraries.  This is accomplished by adding either `-DENABLE_STATIC=0` or
@@ -756,8 +1231,8 @@
 The accuracy of this implementation now matches the accuracy of the SSE/SSE2
 implementation.  Note, however, that the floating point DCT/IDCT algorithms are
 mainly a legacy feature.  They generally do not produce significantly better
-accuracy than the slow integer DCT/IDCT algorithms, and they are quite a bit
-slower.
+accuracy than the accurate integer DCT/IDCT algorithms, and they are quite a
+bit slower.
 
 8. Added a new output colorspace (`JCS_RGB565`) to the libjpeg API that allows
 for decompressing JPEG images into RGB565 (16-bit) pixels.  If dithering is not
@@ -791,13 +1266,13 @@
 reasons (probably related to clang), this code cannot currently be compiled for
 iOS.
 
-15. Fixed an extremely rare bug that could cause the Huffman encoder's local
-buffer to overrun when a very high-frequency MCU is compressed using quality
-100 and no subsampling, and when the JPEG output buffer is being dynamically
-resized by the destination manager.  This issue was so rare that, even with a
-test program specifically designed to make the bug occur (by injecting random
-high-frequency YUV data into the compressor), it was reproducible only once in
-about every 25 million iterations.
+15. Fixed an extremely rare bug (CVE-2014-9092) that could cause the Huffman
+encoder's local buffer to overrun when a very high-frequency MCU is compressed
+using quality 100 and no subsampling, and when the JPEG output buffer is being
+dynamically resized by the destination manager.  This issue was so rare that,
+even with a test program specifically designed to make the bug occur (by
+injecting random high-frequency YUV data into the compressor), it was
+reproducible only once in about every 25 million iterations.
 
 16. Fixed an oversight in the TurboJPEG C wrapper:  if any of the JPEG
 compression functions was called repeatedly with the same
@@ -832,8 +1307,9 @@
 jpegtran, for instance) would result in an error, `Requested feature was
 omitted at compile time`.
 
-4. Fixed a couple of issues whereby malformed JPEG images would cause
-libjpeg-turbo to use uninitialized memory during decompression.
+4. Fixed a couple of issues (CVE-2013-6629 and CVE-2013-6630) whereby malformed
+JPEG images would cause libjpeg-turbo to use uninitialized memory during
+decompression.
 
 5. Fixed an error (`Buffer passed to JPEG library is too small`) that occurred
 when calling the TurboJPEG YUV encoding function with a very small (< 5x5)
@@ -972,9 +1448,9 @@
 upper 64 bits of xmm6 and xmm7 on Win64 platforms, which violated the Win64
 calling conventions.
 
-4. Fixed a regression caused by 1.2.0[6] whereby decompressing corrupt JPEG
-images (specifically, images in which the component count was erroneously set
-to a large value) would cause libjpeg-turbo to segfault.
+4. Fixed a regression (CVE-2012-2806) caused by 1.2.0[6] whereby decompressing
+corrupt JPEG images (specifically, images in which the component count was
+erroneously set to a large value) would cause libjpeg-turbo to segfault.
 
 5. Worked around a severe performance issue with "Bobcat" (AMD Embedded APU)
 processors.  The `MASKMOVDQU` instruction, which was used by the libjpeg-turbo
@@ -1166,8 +1642,8 @@
 
 2. Despite the above, the fast integer forward DCT still degrades somewhat for
 JPEG qualities greater than 95, so the TurboJPEG wrapper will now automatically
-use the slow integer forward DCT when generating JPEG images of quality 96 or
-greater.  This reduces compression performance by as much as 15% for these
+use the accurate integer forward DCT when generating JPEG images of quality 96
+or greater.  This reduces compression performance by as much as 15% for these
 high-quality images but is necessary to ensure that the images are perceptually
 lossless.  It also ensures that the library can avoid the performance pitfall
 created by [1].
diff --git a/src/third_party/libjpeg-turbo/DIR_METADATA b/src/third_party/libjpeg-turbo/DIR_METADATA
new file mode 100644
index 0000000..8bc04f1
--- /dev/null
+++ b/src/third_party/libjpeg-turbo/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "Internals>Images>Codecs"
+}
diff --git a/src/third_party/libjpeg-turbo/LICENSE.md b/src/third_party/libjpeg-turbo/LICENSE.md
index 0f6ec4b..a1cdad5 100644
--- a/src/third_party/libjpeg-turbo/LICENSE.md
+++ b/src/third_party/libjpeg-turbo/LICENSE.md
@@ -14,7 +14,7 @@
   This license covers the TurboJPEG API library and associated programs, as
   well as the build system.
 
-- The zlib License, which is listed below
+- The [zlib License](https://opensource.org/licenses/Zlib)
 
   This license is a subset of the other two, and it covers the libjpeg-turbo
   SIMD extensions.
@@ -66,7 +66,7 @@
 
     2.  If your binary distribution includes or uses the TurboJPEG API, then
         your product documentation must include the text of the Modified BSD
-        License.
+        License (see below.)
 
         **Origin**
         - Clause 2 of the Modified BSD License
@@ -91,7 +91,8 @@
 The Modified (3-clause) BSD License
 ===================================
 
-Copyright (C)\<YEAR\> \<AUTHOR\>.  All Rights Reserved.
+Copyright (C)2009-2021 D. R. Commander.  All Rights Reserved.<br>
+Copyright (C)2015 Viktor Szathmáry.  All Rights Reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -118,28 +119,6 @@
 POSSIBILITY OF SUCH DAMAGE.
 
 
-The zlib License
-================
-
-Copyright (C) \<YEAR\>, \<AUTHOR\>.
-
-This software is provided 'as-is', without any express or implied
-warranty.  In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-   claim that you wrote the original software. If you use this software
-   in a product, an acknowledgment in the product documentation would be
-   appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
-   misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-
 Why Three Licenses?
 ===================
 
diff --git a/src/third_party/libjpeg-turbo/METADATA b/src/third_party/libjpeg-turbo/METADATA
index 35e49ff..81d7ca0 100644
--- a/src/third_party/libjpeg-turbo/METADATA
+++ b/src/third_party/libjpeg-turbo/METADATA
@@ -5,17 +5,14 @@
 third_party {
   url {
     type: GIT
-    value: "https://github.com/libjpeg-turbo/libjpeg-turbo"
+    value: "https://chromium.googlesource.com/chromium/deps/libjpeg_turbo/"
   }
-  # Note: We initially added a version of libjpeg-turbo that was in between
-  # versions 2.0.0 and 1.5.91. The version and last upgrade date below should
-  # reflect the point in between those two versions when the library was first
-  # brought into Cobalt.
-  version: "1a85fc497db85e1bf8b026d51cf6e5dec391d224"
+  # Version 2.1.0
+  version: "b201838d8b5f2f80c9f86ec8405a62a002232b2c"
   last_upgrade_date {
-    year: 2018
-    month: 5
-    day: 21
+    year: 2021
+    month: 7
+    day: 13
   }
   license_type: NOTICE
 }
diff --git a/src/third_party/libjpeg-turbo/README.chromium b/src/third_party/libjpeg-turbo/README.chromium
new file mode 100644
index 0000000..de1fe85
--- /dev/null
+++ b/src/third_party/libjpeg-turbo/README.chromium
@@ -0,0 +1,70 @@
+Name: libjpeg-turbo
+URL: https://github.com/libjpeg-turbo/libjpeg-turbo/
+Version: b201838d8b5f2f80c9f86ec8405a62a002232b2c (post 2.1.0)
+License: Custom license
+License File: LICENSE.md
+Security Critical: yes
+License Android Compatible: yes
+
+Description:
+This consists of the components:
+* libjpeg-turbo b201838d8b5f2f80c9f86ec8405a62a002232b2c (post 2.1.0)
+* This file (README.chromium)
+* A build file (BUILD.gn)
+* An OWNERS file
+* A codereview.settings file
+* Patched header files used by Chromium
+* Deleted unused directories: cmakescripts, doc, fuzz, java, release,
+  sharedlib, simd/loongson, simd/mips, simd/powerpc, and win
+* Deleted unused files: appveyor.yml, CMakeLists.txt, doxygen.config,
+  doxygen-extra.css, .gitattributes, md5/CMakeLists.txt, md5/md5cmp.c,
+  simd/CMakeLists.txt, tjexample.c, tjexampletest.in, tjexampletest.java.in and
+  .travis.yml
+* Deleted legacy Arm Neon assembly files (supporting old compiler versions that
+  do not generate performant code from intrinsics):
+  simd/arm/aarch32/jsimd_neon.S, simd/arm/aarch64/jsimd_neon.S.
+
+This libjpeg-turbo can replace our libjpeg-6b without any modifications in the
+Chromium code.
+
+Same as our copy of libjpeg-6b, this libjpeg-turbo also added a new file
+jpeglibmangler.h and included it from jpeglib.h that changes the names of all
+externally visible functions to chromium_* so that we can avoid conflicts that
+arise when system libraries attempt to use our libjpeg. Also, we applied the
+following changes which are not merged to upstream:
+
+* Configuration files jconfig.h, jconfigint.h and neon-compat.h were generated
+  and then altered manually to be compatible on all of Chromium's platforms.
+  http://crbug.com/608347
+* Fix static const data duplication of jpeg_nbits_table. A unique copy
+  was in the jchuff.obj and jcphuff.obj resulting in an added 65k in
+  .rdata in chrome.dll and chrome_child.dll.  Declaring extern const
+  in the header instead of static const and moving the definition to
+  a new .c file fixes this so only one copy is referenced. Also added
+  extern wrappers around usage in asm files. The jpeg_nbits_table.inc
+  file was also deleted. It was also necessary to give this table hidden
+  visibility to avoid invalid relocations (ignored by ld but rejected by
+  lld) arising from attempts to reference the table from assembler on
+  32-bit x86. This only affects shared libraries, but that's important
+  for downstream Android builds.
+* Patches to enable running the upstream unit tests through GTest.
+  The upstream unit tests are defined here under the section 'TESTS':
+  https://github.com/libjpeg-turbo/libjpeg-turbo/blob/master/CMakeLists.txt
+  These changes are tracked by Chromium issue: https://crbug.com/993876
+  - Refactor tjunittest.c to provide test interface
+  - Move tjunittest logs from stdout to stderr
+  - Refactor tjbench.c to provide test interface
+  - Move tbench logs from stdout to stderr
+  - Write tjunittest output files to sdcard on Android
+  - Refactor cjpeg.c to provide test interface
+  - Refactor jpegtran.c to provide test interface
+  - Add input JPEG images for djpeg and jpegtran tests
+  - Refactor djpeg.c to provide test interface
+  A new gtest directory contains GTest wrappers (and associated utilities) for
+  each of tjunittest, tjbench, cjpeg, djpeg and jpegtran.
+
+Refer to working-with-nested-repos [1] for details of how to setup your git
+svn client to update the code (for making local changes, cherry picking from
+upstream, etc).
+
+[1] https://www.chromium.org/developers/how-tos/get-the-code/working-with-nested-repos
diff --git a/src/third_party/libjpeg-turbo/README.ijg b/src/third_party/libjpeg-turbo/README.ijg
index c4eb7db..9453c19 100644
--- a/src/third_party/libjpeg-turbo/README.ijg
+++ b/src/third_party/libjpeg-turbo/README.ijg
@@ -128,7 +128,7 @@
 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-2016, Thomas G. Lane, Guido Vollbeding.
+This software is copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
 All Rights Reserved except as specified below.
 
 Permission is hereby granted to use, copy, modify, and distribute this
@@ -159,19 +159,6 @@
 assumed by the product vendor.
 
 
-The IJG distribution formerly included code to read and write GIF files.
-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
 ==========
 
@@ -223,12 +210,12 @@
 A PDF file of the older JFIF 1.02 specification is available at
 http://www.w3.org/Graphics/JPEG/jfif3.pdf.
 
-The TIFF 6.0 file format specification can be obtained by FTP from
-ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz.  The JPEG incorporation scheme
-found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
-IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
-Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
-(Compression tag 7).  Copies of this Note can be obtained from
+The TIFF 6.0 file format specification can be obtained from
+http://mirrors.ctan.org/graphics/tiff/TIFF6.ps.gz.  The JPEG incorporation
+scheme found in the TIFF 6.0 spec of 3-June-92 has a number of serious
+problems.  IJG does not recommend use of the TIFF 6.0 design (TIFF Compression
+tag 6).  Instead, we recommend the JPEG design proposed by TIFF Technical Note
+#2 (Compression tag 7).  Copies of this Note can be obtained from
 http://www.ijg.org/files/.  It is expected that the next revision
 of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
 Although IJG's own code does not support TIFF/JPEG, the free libtiff library
@@ -243,14 +230,8 @@
 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
-        send usenet/news.answers/jpeg-faq/part1
-        send usenet/news.answers/jpeg-faq/part2
+general information about JPEG.  It is available at
+http://www.faqs.org/faqs/jpeg-faq.
 
 
 FILE FORMAT COMPATIBILITY
@@ -263,7 +244,7 @@
 are incompatible with the DCT-based JPEG standard or with JFIF (for instance,
 JPEG 2000 and JPEG XR).  This software therefore does not support these
 formats.  Indeed, one of the original reasons for developing this free software
-was to help force convergence on common, interoperable format standards for
+was to help force convergence on a common, interoperable format standard for
 JPEG files.
 
 JFIF is a minimal or "low end" representation.  TIFF/JPEG (TIFF revision 6.0 as
diff --git a/src/third_party/libjpeg-turbo/README.md b/src/third_party/libjpeg-turbo/README.md
index a769259..01e391e 100644
--- a/src/third_party/libjpeg-turbo/README.md
+++ b/src/third_party/libjpeg-turbo/README.md
@@ -1,14 +1,14 @@
 Background
 ==========
 
-libjpeg-turbo is a JPEG image codec that uses SIMD instructions (MMX, SSE2,
-AVX2, NEON, AltiVec) to accelerate baseline JPEG compression and decompression
-on x86, x86-64, ARM, and PowerPC systems, as well as progressive JPEG
-compression on x86 and x86-64 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 is a JPEG image codec that uses SIMD instructions to accelerate
+baseline JPEG compression and decompression on x86, x86-64, Arm, PowerPC, and
+MIPS systems, as well as progressive JPEG compression on x86, x86-64, and Arm
+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
@@ -135,25 +135,24 @@
 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 `-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
 
 #### Fully supported
 
-- **libjpeg: IDCT scaling extensions in decompressor**<br>
+- **libjpeg API: IDCT scaling extensions in decompressor**<br>
   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 API: Arithmetic coding**
 
-- **libjpeg: In-memory source and destination managers**<br>
+- **libjpeg API: In-memory source and destination managers**<br>
   See notes below.
 
 - **cjpeg: Separate quality settings for luminance and chrominance**<br>
@@ -180,19 +179,19 @@
 
 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,
+means of quality improvement.  Readers are invited to peruse the research at
+<http://www.libjpeg-turbo.org/About/SmartScale> and draw their 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**<br>
+- **libjpeg API: DCT scaling in compressor**<br>
   `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**<br>
+- **libjpeg API: SmartScale**<br>
   `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
@@ -205,7 +204,7 @@
   interest in providing this feature would be as a means of supporting
   additional DCT scaling factors.
 
-- **libjpeg: Fancy downsampling in compressor**<br>
+- **libjpeg API: Fancy downsampling in compressor**<br>
   `cinfo.do_fancy_downsampling` is silently ignored.
   This requires the DCT scaling feature, which is not supported.
 
@@ -247,15 +246,14 @@
 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
+v6b or v7 API can pass 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.1.0 to 62.2.0 if using libjpeg v6b API/ABI
-emulation and from 7.1.0 to 7.2.0 if using libjpeg v7 API/ABI emulation.
+the dynamic library version from 62.2.0 to 62.3.0 if using libjpeg v6b API/ABI
+emulation and from 7.2.0 to 7.3.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
@@ -289,12 +287,13 @@
   (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.)
+  point IDCT in line with the accuracy of the accurate integer IDCT.  The
+  floating point DCT/IDCT algorithms are mainly a legacy feature, and they do
+  not produce significantly more accuracy than the accurate 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
@@ -331,7 +330,7 @@
 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
+libjpeg.  Many consumer packages, such as Photoshop, use restart markers when
 generating JPEG images, so images generated by those programs will experience
 this issue.
 
@@ -342,5 +341,17 @@
 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
+It is therefore strongly advised that you use the accurate integer forward DCT
 whenever encoding images with a JPEG quality of 98 or higher.
+
+
+Memory Debugger Pitfalls
+========================
+
+Valgrind and Memory Sanitizer (MSan) can generate false positives
+(specifically, incorrect reports of uninitialized memory accesses) when used
+with libjpeg-turbo's SIMD extensions.  It is generally recommended that the
+SIMD extensions be disabled, either by passing an argument of `-DWITH_SIMD=0`
+to `cmake` when configuring the build or by setting the environment variable
+`JSIMD_FORCENONE` to `1` at run time, when testing libjpeg-turbo with Valgrind,
+MSan, or other memory debuggers.
diff --git a/src/third_party/libjpeg-turbo/cderror.h b/src/third_party/libjpeg-turbo/cderror.h
index 37034a9..2844346 100644
--- a/src/third_party/libjpeg-turbo/cderror.h
+++ b/src/third_party/libjpeg-turbo/cderror.h
@@ -1,9 +1,11 @@
 /*
  * cderror.h
  *
+ * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1997, Thomas G. Lane.
- * Modified 2009 by Guido Vollbeding.
- * This file is part of the Independent JPEG Group's software.
+ * Modified 2009-2017 by Guido Vollbeding.
+ * libjpeg-turbo Modifications:
+ * Copyright (C) 2021, D. R. Commander.
  * For conditions of distribution and use, see the accompanying README.ijg
  * file.
  *
@@ -42,16 +44,17 @@
 
 #ifdef BMP_SUPPORTED
 JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format")
-JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported")
+JMESSAGE(JERR_BMP_BADDEPTH, "Only 8-, 24-, and 32-bit BMP files are supported")
 JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length")
 JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1")
 JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
 JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
 JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image")
 JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
-JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image")
+JMESSAGE(JERR_BMP_OUTOFRANGE, "Numeric value out of range in BMP file")
+JMESSAGE(JTRC_BMP, "%ux%u %d-bit BMP image")
 JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
-JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image")
+JMESSAGE(JTRC_BMP_OS2, "%ux%u %d-bit OS2 BMP image")
 JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
 #endif /* BMP_SUPPORTED */
 
@@ -59,6 +62,7 @@
 JMESSAGE(JERR_GIF_BUG, "GIF output got confused")
 JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d")
 JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB")
+JMESSAGE(JERR_GIF_EMPTY, "Empty GIF image")
 JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file")
 JMESSAGE(JERR_GIF_NOT, "Not a GIF file")
 JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image")
@@ -75,31 +79,14 @@
 #ifdef PPM_SUPPORTED
 JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB")
 JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file")
-JMESSAGE(JERR_PPM_TOOLARGE, "Integer value too large in PPM file")
 JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file")
+JMESSAGE(JERR_PPM_OUTOFRANGE, "Numeric value out of range in PPM file")
 JMESSAGE(JTRC_PGM, "%ux%u PGM image")
 JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image")
 JMESSAGE(JTRC_PPM, "%ux%u PPM image")
 JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image")
 #endif /* PPM_SUPPORTED */
 
-#ifdef RLE_SUPPORTED
-JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library")
-JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB")
-JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE")
-JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file")
-JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header")
-JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header")
-JMESSAGE(JERR_RLE_NOT, "Not an RLE file")
-JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE")
-JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup")
-JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file")
-JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d")
-JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file")
-JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d")
-JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d")
-#endif /* RLE_SUPPORTED */
-
 #ifdef TARGA_SUPPORTED
 JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format")
 JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file")
diff --git a/src/third_party/libjpeg-turbo/cdjpeg.c b/src/third_party/libjpeg-turbo/cdjpeg.c
index e0e382d..5278c1d 100644
--- a/src/third_party/libjpeg-turbo/cdjpeg.c
+++ b/src/third_party/libjpeg-turbo/cdjpeg.c
@@ -3,8 +3,8 @@
  *
  * 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.
+ * libjpeg-turbo Modifications:
+ * Copyright (C) 2019, D. R. Commander.
  * For conditions of distribution and use, see the accompanying README.ijg
  * file.
  *
@@ -25,26 +25,37 @@
  * Optional progress monitor: display a percent-done figure on stderr.
  */
 
-#ifdef PROGRESS_REPORT
-
 METHODDEF(void)
 progress_monitor(j_common_ptr cinfo)
 {
   cd_progress_ptr prog = (cd_progress_ptr)cinfo->progress;
-  int total_passes = prog->pub.total_passes + prog->total_extra_passes;
-  int percent_done =
-    (int)(prog->pub.pass_counter * 100L / prog->pub.pass_limit);
 
-  if (percent_done != prog->percent_done) {
-    prog->percent_done = percent_done;
-    if (total_passes > 1) {
-      fprintf(stderr, "\rPass %d/%d: %3d%% ",
-              prog->pub.completed_passes + prog->completed_extra_passes + 1,
-              total_passes, percent_done);
-    } else {
-      fprintf(stderr, "\r %3d%% ", percent_done);
+  if (prog->max_scans != 0 && cinfo->is_decompressor) {
+    int scan_no = ((j_decompress_ptr)cinfo)->input_scan_number;
+
+    if (scan_no > (int)prog->max_scans) {
+      fprintf(stderr, "Scan number %d exceeds maximum scans (%d)\n", scan_no,
+              prog->max_scans);
+      exit(EXIT_FAILURE);
     }
-    fflush(stderr);
+  }
+
+  if (prog->report) {
+    int total_passes = prog->pub.total_passes + prog->total_extra_passes;
+    int percent_done =
+      (int)(prog->pub.pass_counter * 100L / prog->pub.pass_limit);
+
+    if (percent_done != prog->percent_done) {
+      prog->percent_done = percent_done;
+      if (total_passes > 1) {
+        fprintf(stderr, "\rPass %d/%d: %3d%% ",
+                prog->pub.completed_passes + prog->completed_extra_passes + 1,
+                total_passes, percent_done);
+      } else {
+        fprintf(stderr, "\r %3d%% ", percent_done);
+      }
+      fflush(stderr);
+    }
   }
 }
 
@@ -57,6 +68,8 @@
     progress->pub.progress_monitor = progress_monitor;
     progress->completed_extra_passes = 0;
     progress->total_extra_passes = 0;
+    progress->max_scans = 0;
+    progress->report = FALSE;
     progress->percent_done = -1;
     cinfo->progress = &progress->pub;
   }
@@ -73,8 +86,6 @@
   }
 }
 
-#endif
-
 
 /*
  * Case-insensitive matching of possibly-abbreviated keyword switches.
diff --git a/src/third_party/libjpeg-turbo/cdjpeg.h b/src/third_party/libjpeg-turbo/cdjpeg.h
index c93f3ab..86e47c9 100644
--- a/src/third_party/libjpeg-turbo/cdjpeg.h
+++ b/src/third_party/libjpeg-turbo/cdjpeg.h
@@ -3,8 +3,9 @@
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1994-1997, Thomas G. Lane.
+ * Modified 2019 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2017, D. R. Commander.
+ * Copyright (C) 2017, 2019, 2021, D. R. Commander.
  * For conditions of distribution and use, see the accompanying README.ijg
  * file.
  *
@@ -31,10 +32,17 @@
   JDIMENSION (*get_pixel_rows) (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
   void (*finish_input) (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
 
+#if defined(STARBOARD)
   SbFile *input_file;
+#else
+  FILE *input_file;
+#endif
 
   JSAMPARRAY buffer;
   JDIMENSION buffer_height;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+  JDIMENSION max_pixels;
+#endif
 };
 
 
@@ -56,15 +64,19 @@
   void (*finish_output) (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo);
   /* Re-calculate buffer dimensions based on output dimensions (for use with
      partial image decompression.)  If this is NULL, then the output format
-     does not support partial image decompression (BMP and RLE, in particular,
-     cannot support partial decompression because they use an inversion buffer
-     to write the image in bottom-up order.) */
+     does not support partial image decompression (BMP, in particular, cannot
+     support partial decompression because it uses an inversion buffer to write
+     the image in bottom-up order.) */
   void (*calc_buffer_dimensions) (j_decompress_ptr cinfo,
                                   djpeg_dest_ptr dinfo);
 
 
   /* Target file spec; filled in by djpeg.c after object is created. */
+#if defined(STARBOARD)
   SbFile *output_file;
+#else
+  FILE *output_file;
+#endif
 
   /* Output pixel-row buffer.  Created by module init or start_output.
    * Width is cinfo->output_width * cinfo->output_components;
@@ -87,6 +99,9 @@
   struct jpeg_progress_mgr pub; /* fields known to JPEG library */
   int completed_extra_passes;   /* extra passes completed */
   int total_extra_passes;       /* total extra */
+  JDIMENSION max_scans;         /* abort if the number of scans exceeds this
+                                   value and the value is non-zero */
+  boolean report;               /* whether or not to report progress */
   /* last printed percentage stored here to avoid multiple printouts */
   int percent_done;
 };
@@ -101,11 +116,9 @@
 EXTERN(djpeg_dest_ptr) jinit_write_bmp(j_decompress_ptr cinfo, boolean is_os2,
                                        boolean use_inversion_array);
 EXTERN(cjpeg_source_ptr) jinit_read_gif(j_compress_ptr cinfo);
-EXTERN(djpeg_dest_ptr) jinit_write_gif(j_decompress_ptr cinfo);
+EXTERN(djpeg_dest_ptr) jinit_write_gif(j_decompress_ptr cinfo, boolean is_lzw);
 EXTERN(cjpeg_source_ptr) jinit_read_ppm(j_compress_ptr cinfo);
 EXTERN(djpeg_dest_ptr) jinit_write_ppm(j_decompress_ptr cinfo);
-EXTERN(cjpeg_source_ptr) jinit_read_rle(j_compress_ptr cinfo);
-EXTERN(djpeg_dest_ptr) jinit_write_rle(j_decompress_ptr cinfo);
 EXTERN(cjpeg_source_ptr) jinit_read_targa(j_compress_ptr cinfo);
 EXTERN(djpeg_dest_ptr) jinit_write_targa(j_decompress_ptr cinfo);
 
@@ -121,17 +134,26 @@
 
 /* djpeg support routines (in rdcolmap.c) */
 
+#if defined(STARBOARD)
 EXTERN(void) read_color_map(j_decompress_ptr cinfo, SbFile *infile);
+#else
+EXTERN(void) read_color_map(j_decompress_ptr cinfo, FILE *infile);
+#endif
 
 /* common support routines (in cdjpeg.c) */
 
-EXTERN(void) enable_signal_catcher(j_common_ptr cinfo);
 EXTERN(void) start_progress_monitor(j_common_ptr cinfo,
                                     cd_progress_ptr progress);
 EXTERN(void) end_progress_monitor(j_common_ptr cinfo);
 EXTERN(boolean) keymatch(char *arg, const char *keyword, int minchars);
+
+#if defined(STARBOARD)
 EXTERN(SbFile *) read_stdin(void);
 EXTERN(SbFile *) write_stdout(void);
+#else
+EXTERN(FILE *) read_stdin(void);
+EXTERN(FILE *) write_stdout(void);
+#endif
 
 /* miscellaneous useful macros */
 
diff --git a/src/third_party/libjpeg-turbo/change.log b/src/third_party/libjpeg-turbo/change.log
index f090d77..e4d0ddc 100644
--- a/src/third_party/libjpeg-turbo/change.log
+++ b/src/third_party/libjpeg-turbo/change.log
@@ -6,6 +6,25 @@
 CHANGE LOG for Independent JPEG Group's JPEG software
 
 
+Version 9d  12-Jan-2020
+-----------------------
+
+Restore GIF read and write support from libjpeg version 6a.
+Thank to Wolfgang Werner (W.W.) Heinz for suggestion.
+
+Add jpegtran -drop option; add options to the crop extension and wipe
+to fill the extra area with content from the source image region,
+instead of gray out.
+
+
+Version 9c  14-Jan-2018
+-----------------------
+
+jpegtran: add an option to the -wipe switch to fill the region
+with the average of adjacent blocks, instead of gray out.
+Thank to Caitlyn Feddock and Maddie Ziegler for inspiration.
+
+
 Version 9b  17-Jan-2016
 -----------------------
 
@@ -13,6 +32,13 @@
 Thank to Michele Martone for suggestion.
 
 
+Version 9a  19-Jan-2014
+-----------------------
+
+Add jpegtran -wipe option and extension for -crop.
+Thank to Andrew Senior, David Clunie, and Josef Schmid for suggestion.
+
+
 Version 9  13-Jan-2013
 ----------------------
 
@@ -138,11 +164,6 @@
 
 Huffman tables are checked for validity much more carefully than before.
 
-To avoid the Unisys LZW patent, djpeg's GIF output capability has been
-changed to produce "uncompressed GIFs", and cjpeg's GIF input capability
-has been removed altogether.  We're not happy about it either, but there
-seems to be no good alternative.
-
 The configure script now supports building libjpeg as a shared library
 on many flavors of Unix (all the ones that GNU libtool knows how to
 build shared libraries for).  Use "./configure --enable-shared" to
diff --git a/src/third_party/libjpeg-turbo/cjpeg.1 b/src/third_party/libjpeg-turbo/cjpeg.1
index a3e47ba..569dc3f 100644
--- a/src/third_party/libjpeg-turbo/cjpeg.1
+++ b/src/third_party/libjpeg-turbo/cjpeg.1
@@ -1,4 +1,4 @@
-.TH CJPEG 1 "18 March 2017"
+.TH CJPEG 1 "4 November 2020"
 .SH NAME
 cjpeg \- compress an image file to a JPEG file
 .SH SYNOPSIS
@@ -16,8 +16,7 @@
 compresses the named image file, or the standard input if no file is
 named, and produces a JPEG/JFIF file on the standard output.
 The currently supported input file formats are: PPM (PBMPLUS color
-format), PGM (PBMPLUS grayscale format), BMP, Targa, and RLE (Utah Raster
-Toolkit format).  (RLE is supported only if the URT library is available.)
+format), PGM (PBMPLUS grayscale format), BMP, GIF, and Targa.
 .SH OPTIONS
 All switch names may be abbreviated; for example,
 .B \-grayscale
@@ -42,10 +41,10 @@
 .TP
 .B \-grayscale
 Create monochrome JPEG file from color input.  Be sure to use this switch when
-compressing a grayscale BMP file, because
+compressing a grayscale BMP or GIF file, because
 .B cjpeg
-isn't bright enough to notice whether a BMP file uses only shades of gray.
-By saying
+isn't bright enough to notice whether a BMP or GIF file uses only shades of
+gray.  By saying
 .BR \-grayscale,
 you'll get a smaller JPEG file that takes less time to process.
 .TP
@@ -161,31 +160,40 @@
 unable to view an arithmetic coded JPEG file at all.
 .TP
 .B \-dct int
-Use integer DCT method (default).
+Use accurate integer DCT method (default).
 .TP
 .B \-dct fast
-Use fast integer DCT (less accurate).
-In libjpeg-turbo, the fast method is generally about 5-15% faster than the int
-method when using the x86/x86-64 SIMD extensions (results may vary with other
-SIMD implementations, or when using libjpeg-turbo without SIMD extensions.)
+Use less accurate integer DCT method [legacy feature].
+When the Independent JPEG Group's software was first released in 1991, the
+compression time for a 1-megapixel JPEG image on a mainstream PC was measured
+in minutes.  Thus, the \fBfast\fR integer DCT algorithm provided noticeable
+performance benefits.  On modern CPUs running libjpeg-turbo, however, the
+compression time for a 1-megapixel JPEG image is measured in milliseconds, and
+thus the performance benefits of the \fBfast\fR algorithm are much less
+noticeable.  On modern x86/x86-64 CPUs that support AVX2 instructions, the
+\fBfast\fR and \fBint\fR methods have similar performance.  On other types of
+CPUs, the \fBfast\fR method is generally about 5-15% faster than the \fBint\fR
+method.
+
 For quality levels of 90 and below, there should be little or no perceptible
-difference between the two algorithms.  For quality levels above 90, however,
-the difference between the fast and the int methods becomes more pronounced.
-With quality=97, for instance, the fast method incurs generally about a 1-3 dB
-loss (in PSNR) relative to the int method, but this can be larger for some
-images.  Do not use the fast method with quality levels above 97.  The
-algorithm often degenerates at quality=98 and above and can actually produce a
-more lossy image than if lower quality levels had been used.  Also, in
-libjpeg-turbo, the fast method is not fully accelerated for quality levels
-above 97, so it will be slower than the int method.
+quality difference between the two algorithms.  For quality levels above 90,
+however, the difference between the \fBfast\fR and \fBint\fR methods becomes
+more pronounced.  With quality=97, for instance, the \fBfast\fR method incurs
+generally about a 1-3 dB loss in PSNR relative to the \fBint\fR method, but
+this can be larger for some images.  Do not use the \fBfast\fR method with
+quality levels above 97.  The algorithm often degenerates at quality=98 and
+above and can actually produce a more lossy image than if lower quality levels
+had been used.  Also, in libjpeg-turbo, the \fBfast\fR method is not fully
+accelerated for quality levels above 97, so it will be slower than the
+\fBint\fR method.
 .TP
 .B \-dct float
-Use floating-point DCT method.
-The float method is mainly a legacy feature.  It does not produce significantly
-more accurate results than the int method, and it is much slower.  The float
-method may also give different results on different machines due to varying
-roundoff behavior, whereas the integer methods should give the same results on
-all machines.
+Use floating-point DCT method [legacy feature].
+The \fBfloat\fR method does not produce significantly more accurate results
+than the \fBint\fR method, and it is much slower.  The \fBfloat\fR method may
+also give different results on different machines due to varying roundoff
+behavior, whereas the integer methods should give the same results on all
+machines.
 .TP
 .BI \-icc " file"
 Embed ICC color management profile contained in the specified file.
@@ -215,6 +223,9 @@
 way of testing the in-memory destination manager (jpeg_mem_dest()), but it is
 also useful for benchmarking, since it reduces the I/O overhead.
 .TP
+.BI \-report
+Report compression progress.
+.TP
 .B \-verbose
 Enable debug printout.  More
 .BR \-v 's
@@ -341,11 +352,6 @@
 relevant to libjpeg-turbo, to wordsmith certain sections, and to describe
 features not present in libjpeg.
 .SH ISSUES
-Support for GIF input files was removed in cjpeg v6b due to concerns over
-the Unisys LZW patent.  Although this patent expired in 2006, cjpeg still
-lacks GIF support, for these historical reasons.  (Conversion of GIF files to
-JPEG is usually a bad idea anyway, since GIF is a 256-color format.)
-.PP
 Not all variants of BMP and Targa file formats are supported.
 .PP
 The
diff --git a/src/third_party/libjpeg-turbo/cjpeg.c b/src/third_party/libjpeg-turbo/cjpeg.c
index 07e7db1..66ac28f 100644
--- a/src/third_party/libjpeg-turbo/cjpeg.c
+++ b/src/third_party/libjpeg-turbo/cjpeg.c
@@ -5,7 +5,7 @@
  * Copyright (C) 1991-1998, Thomas G. Lane.
  * Modified 2003-2011 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2013-2014, 2017, D. R. Commander.
+ * Copyright (C) 2010, 2013-2014, 2017, 2019-2021, D. R. Commander.
  * For conditions of distribution and use, see the accompanying README.ijg
  * file.
  *
@@ -27,6 +27,9 @@
  * works regardless of which command line style is used.
  */
 
+#ifdef CJPEG_FUZZER
+#define JPEG_INTERNALS
+#endif
 #include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */
 #include "jversion.h"           /* for version message */
 #include "jconfigint.h"
@@ -69,9 +72,9 @@
  *     2) assume we can push back more than one character (works in
  *        some C implementations, but unportable);
  *     3) provide our own buffering (breaks input readers that want to use
- *        stdio directly, such as the RLE library);
+ *        stdio directly);
  * or  4) don't put back the data, and modify the input_init methods to assume
- *        they start reading after the start of file (also breaks RLE library).
+ *        they start reading after the start of file.
  * #1 is attractive for MS-DOS but is untenable on Unix.
  *
  * The most portable solution for file types that can't be identified by their
@@ -117,10 +120,6 @@
   case 'P':
     return jinit_read_ppm(cinfo);
 #endif
-#ifdef RLE_SUPPORTED
-  case 'R':
-    return jinit_read_rle(cinfo);
-#endif
 #ifdef TARGA_SUPPORTED
   case 0x00:
     return jinit_read_targa(cinfo);
@@ -147,6 +146,46 @@
 static char *icc_filename;      /* for -icc switch */
 static char *outfilename;       /* for -outfile switch */
 boolean memdst;                 /* for -memdst switch */
+boolean report;                 /* for -report switch */
+
+
+#ifdef CJPEG_FUZZER
+
+#include <setjmp.h>
+
+struct my_error_mgr {
+  struct jpeg_error_mgr pub;
+  jmp_buf setjmp_buffer;
+};
+
+void my_error_exit(j_common_ptr cinfo)
+{
+  struct my_error_mgr *myerr = (struct my_error_mgr *)cinfo->err;
+
+  longjmp(myerr->setjmp_buffer, 1);
+}
+
+static void my_emit_message(j_common_ptr cinfo, int msg_level)
+{
+  if (msg_level < 0)
+    cinfo->err->num_warnings++;
+}
+
+#define HANDLE_ERROR() { \
+  if (cinfo.global_state > CSTATE_START) { \
+    if (memdst && outbuffer) \
+      (*cinfo.dest->term_destination) (&cinfo); \
+    jpeg_abort_compress(&cinfo); \
+  } \
+  jpeg_destroy_compress(&cinfo); \
+  if (input_file != stdin && input_file != NULL) \
+    fclose(input_file); \
+  if (memdst) \
+    free(outbuffer); \
+  return EXIT_FAILURE; \
+}
+
+#endif
 
 
 LOCAL(void)
@@ -179,15 +218,15 @@
   fprintf(stderr, "  -arithmetic    Use arithmetic coding\n");
 #endif
 #ifdef DCT_ISLOW_SUPPORTED
-  fprintf(stderr, "  -dct int       Use integer DCT method%s\n",
+  fprintf(stderr, "  -dct int       Use accurate integer DCT method%s\n",
           (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
 #endif
 #ifdef DCT_IFAST_SUPPORTED
-  fprintf(stderr, "  -dct fast      Use fast integer DCT (less accurate)%s\n",
+  fprintf(stderr, "  -dct fast      Use less accurate integer DCT method [legacy feature]%s\n",
           (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
 #endif
 #ifdef DCT_FLOAT_SUPPORTED
-  fprintf(stderr, "  -dct float     Use floating-point DCT method%s\n",
+  fprintf(stderr, "  -dct float     Use floating-point DCT method [legacy feature]%s\n",
           (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
 #endif
   fprintf(stderr, "  -icc FILE      Embed ICC profile contained in FILE\n");
@@ -200,6 +239,7 @@
 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
   fprintf(stderr, "  -memdst        Compress to memory instead of file (useful for benchmarking)\n");
 #endif
+  fprintf(stderr, "  -report        Report compression progress\n");
   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
   fprintf(stderr, "  -version       Print version information and exit\n");
   fprintf(stderr, "Switches for wizards:\n");
@@ -244,6 +284,7 @@
   icc_filename = NULL;
   outfilename = NULL;
   memdst = FALSE;
+  report = FALSE;
   cinfo->err->trace_level = 0;
 
   /* Scan command line options, adjust parameters */
@@ -395,6 +436,9 @@
       qtablefile = argv[argn];
       /* We postpone actually reading the file in case -quality comes later. */
 
+    } else if (keymatch(arg, "report", 3)) {
+      report = TRUE;
+
     } else if (keymatch(arg, "restart", 1)) {
       /* Restart interval in MCU rows (or in MCUs with 'b'). */
       long lval;
@@ -501,16 +545,23 @@
  */
 
 int
+#ifdef GTEST
+cjpeg(int argc, char **argv)
+#else
 main(int argc, char **argv)
+#endif
 {
   struct jpeg_compress_struct cinfo;
+#ifdef CJPEG_FUZZER
+  struct my_error_mgr myerr;
+  struct jpeg_error_mgr &jerr = myerr.pub;
+#else
   struct jpeg_error_mgr jerr;
-#ifdef PROGRESS_REPORT
-  struct cdjpeg_progress_mgr progress;
 #endif
+  struct cdjpeg_progress_mgr progress;
   int file_index;
   cjpeg_source_ptr src_mgr;
-  FILE *input_file;
+  FILE *input_file = NULL;
   FILE *icc_file;
   JOCTET *icc_profile = NULL;
   long icc_len = 0;
@@ -583,7 +634,7 @@
   if (file_index < argc) {
     if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
   } else {
     /* default input file is stdin */
@@ -594,7 +645,7 @@
   if (outfilename != NULL) {
     if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
       fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
   } else if (!memdst) {
     /* default output file is stdout */
@@ -604,37 +655,48 @@
   if (icc_filename != NULL) {
     if ((icc_file = fopen(icc_filename, READ_BINARY)) == NULL) {
       fprintf(stderr, "%s: can't open %s\n", progname, icc_filename);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
     if (fseek(icc_file, 0, SEEK_END) < 0 ||
         (icc_len = ftell(icc_file)) < 1 ||
         fseek(icc_file, 0, SEEK_SET) < 0) {
       fprintf(stderr, "%s: can't determine size of %s\n", progname,
               icc_filename);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
     if ((icc_profile = (JOCTET *)malloc(icc_len)) == NULL) {
       fprintf(stderr, "%s: can't allocate memory for ICC profile\n", progname);
       fclose(icc_file);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
     if (fread(icc_profile, icc_len, 1, icc_file) < 1) {
       fprintf(stderr, "%s: can't read ICC profile from %s\n", progname,
               icc_filename);
       free(icc_profile);
       fclose(icc_file);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
     fclose(icc_file);
   }
 
-#ifdef PROGRESS_REPORT
-  start_progress_monitor((j_common_ptr)&cinfo, &progress);
+#ifdef CJPEG_FUZZER
+  jerr.error_exit = my_error_exit;
+  jerr.emit_message = my_emit_message;
+  if (setjmp(myerr.setjmp_buffer))
+    HANDLE_ERROR()
 #endif
 
+  if (report) {
+    start_progress_monitor((j_common_ptr)&cinfo, &progress);
+    progress.report = report;
+  }
+
   /* Figure out the input file format, and set up to read it. */
   src_mgr = select_file_type(&cinfo, input_file);
   src_mgr->input_file = input_file;
+#ifdef CJPEG_FUZZER
+  src_mgr->max_pixels = 1048576;
+#endif
 
   /* Read the input file header to obtain file size & colorspace. */
   (*src_mgr->start_input) (&cinfo, src_mgr);
@@ -653,6 +715,11 @@
 #endif
     jpeg_stdio_dest(&cinfo, output_file);
 
+#ifdef CJPEG_FUZZER
+  if (setjmp(myerr.setjmp_buffer))
+    HANDLE_ERROR()
+#endif
+
   /* Start compressor */
   jpeg_start_compress(&cinfo, TRUE);
 
@@ -676,20 +743,18 @@
   if (output_file != stdout && output_file != NULL)
     fclose(output_file);
 
-#ifdef PROGRESS_REPORT
-  end_progress_monitor((j_common_ptr)&cinfo);
-#endif
+  if (report)
+    end_progress_monitor((j_common_ptr)&cinfo);
 
   if (memdst) {
+#ifndef CJPEG_FUZZER
     fprintf(stderr, "Compressed size:  %lu bytes\n", outsize);
-    if (outbuffer != NULL)
-      free(outbuffer);
+#endif
+    free(outbuffer);
   }
 
-  if (icc_profile != NULL)
-    free(icc_profile);
+  free(icc_profile);
 
   /* All done. */
-  exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
-  return 0;                     /* suppress no-return-value warnings */
+  return (jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
 }
diff --git a/src/third_party/libjpeg-turbo/cmakescripts/BuildPackages.cmake b/src/third_party/libjpeg-turbo/cmakescripts/BuildPackages.cmake
deleted file mode 100644
index 57f0672..0000000
--- a/src/third_party/libjpeg-turbo/cmakescripts/BuildPackages.cmake
+++ /dev/null
@@ -1,177 +0,0 @@
-# This file is included from the top-level CMakeLists.txt.  We just store it
-# here to avoid cluttering up that file.
-
-set(PKGNAME ${CMAKE_PROJECT_NAME} CACHE STRING
-  "Distribution package name (default: ${CMAKE_PROJECT_NAME})")
-set(PKGVENDOR "The ${CMAKE_PROJECT_NAME} Project" CACHE STRING
-  "Vendor name to be included in distribution package descriptions (default: The ${CMAKE_PROJECT_NAME} Project)")
-set(PKGURL "http://www.${CMAKE_PROJECT_NAME}.org" CACHE STRING
-  "URL of project web site to be included in distribution package descriptions (default: http://www.${CMAKE_PROJECT_NAME}.org)")
-set(PKGEMAIL "information@${CMAKE_PROJECT_NAME}.org" CACHE STRING
-  "E-mail of project maintainer to be included in distribution package descriptions (default: information@${CMAKE_PROJECT_NAME}.org")
-set(PKGID "com.${CMAKE_PROJECT_NAME}.${PKGNAME}" CACHE STRING
-  "Globally unique package identifier (reverse DNS notation) (default: com.${CMAKE_PROJECT_NAME}.${PKGNAME})")
-
-
-###############################################################################
-# Linux RPM and DEB
-###############################################################################
-
-if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
-
-set(RPMARCH ${CMAKE_SYSTEM_PROCESSOR})
-if(CPU_TYPE STREQUAL "x86_64")
-  set(DEBARCH amd64)
-elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "armv7*")
-  set(DEBARCH armhf)
-elseif(CPU_TYPE STREQUAL "arm64")
-  set(DEBARCH ${CPU_TYPE})
-elseif(CPU_TYPE STREQUAL "arm")
-  set(DEBARCH armel)
-elseif(CMAKE_SYSTEM_PROCESSOR_LC STREQUAL "ppc64le")
-  set(DEBARCH ppc64el)
-elseif(CPU_TYPE STREQUAL "powerpc" AND BITS EQUAL 32)
-  set(RPMARCH ppc)
-  set(DEBARCH ppc)
-else()
-  set(DEBARCH ${CMAKE_SYSTEM_PROCESSOR})
-endif()
-message(STATUS "RPM architecture = ${RPMARCH}, DEB architecture = ${DEBARCH}")
-
-# Re-set CMAKE_POSITION_INDEPENDENT_CODE so that the RPM spec file works
-# properly
-boolean_number(CMAKE_POSITION_INDEPENDENT_CODE)
-
-configure_file(release/makerpm.in pkgscripts/makerpm)
-configure_file(release/rpm.spec.in pkgscripts/rpm.spec @ONLY)
-
-add_custom_target(rpm sh pkgscripts/makerpm
-  SOURCES pkgscripts/makerpm)
-
-configure_file(release/makesrpm.in pkgscripts/makesrpm)
-
-add_custom_target(srpm sh pkgscripts/makesrpm
-  SOURCES pkgscripts/makesrpm
-  DEPENDS dist)
-
-configure_file(release/makedpkg.in pkgscripts/makedpkg)
-configure_file(release/deb-control.in pkgscripts/deb-control)
-
-add_custom_target(deb sh pkgscripts/makedpkg
-  SOURCES pkgscripts/makedpkg)
-
-endif() # Linux
-
-
-###############################################################################
-# Windows installer (NullSoft Installer)
-###############################################################################
-
-if(WIN32)
-
-if(MSVC)
-  set(INST_PLATFORM "Visual C++")
-  set(INST_NAME ${CMAKE_PROJECT_NAME}-${VERSION}-vc)
-  set(INST_REG_NAME ${CMAKE_PROJECT_NAME})
-elseif(MINGW)
-  set(INST_PLATFORM GCC)
-  set(INST_NAME ${CMAKE_PROJECT_NAME}-${VERSION}-gcc)
-  set(INST_REG_NAME ${CMAKE_PROJECT_NAME}-gcc)
-  set(INST_DEFS -DGCC)
-endif()
-
-if(BITS EQUAL 64)
-  set(INST_PLATFORM "${INST_PLATFORM} 64-bit")
-  set(INST_NAME ${INST_NAME}64)
-  set(INST_REG_NAME ${INST_DIR}64)
-  set(INST_DEFS ${INST_DEFS} -DWIN64)
-endif()
-
-if(WITH_JAVA)
-  set(INST_DEFS ${INST_DEFS} -DJAVA)
-endif()
-
-if(MSVC_IDE)
-  set(INST_DEFS ${INST_DEFS} "-DBUILDDIR=${CMAKE_CFG_INTDIR}\\")
-else()
-  set(INST_DEFS ${INST_DEFS} "-DBUILDDIR=")
-endif()
-
-string(REGEX REPLACE "/" "\\\\" INST_DIR ${CMAKE_INSTALL_PREFIX})
-
-configure_file(release/installer.nsi.in installer.nsi @ONLY)
-
-if(WITH_JAVA)
-  set(JAVA_DEPEND turbojpeg-java)
-endif()
-add_custom_target(installer
-  makensis -nocd ${INST_DEFS} installer.nsi
-  DEPENDS jpeg jpeg-static turbojpeg turbojpeg-static rdjpgcom wrjpgcom
-    cjpeg djpeg jpegtran tjbench ${JAVA_DEPEND}
-  SOURCES installer.nsi)
-
-endif() # WIN32
-
-
-###############################################################################
-# Cygwin Package
-###############################################################################
-
-if(CYGWIN)
-
-configure_file(release/makecygwinpkg.in pkgscripts/makecygwinpkg)
-
-add_custom_target(cygwinpkg sh pkgscripts/makecygwinpkg)
-
-endif() # CYGWIN
-
-
-###############################################################################
-# Mac DMG
-###############################################################################
-
-if(APPLE)
-
-set(DEFAULT_OSX_32BIT_BUILD ${CMAKE_SOURCE_DIR}/osxx86)
-set(OSX_32BIT_BUILD ${DEFAULT_OSX_32BIT_BUILD} CACHE PATH
-  "Directory containing 32-bit (i386) Mac build to include in universal binaries (default: ${DEFAULT_OSX_32BIT_BUILD})")
-set(DEFAULT_IOS_ARMV7_BUILD ${CMAKE_SOURCE_DIR}/iosarmv7)
-set(IOS_ARMV7_BUILD ${DEFAULT_IOS_ARMV7_BUILD} CACHE PATH
-  "Directory containing ARMv7 iOS build to include in universal binaries (default: ${DEFAULT_IOS_ARMV7_BUILD})")
-set(DEFAULT_IOS_ARMV7S_BUILD ${CMAKE_SOURCE_DIR}/iosarmv7s)
-set(IOS_ARMV7S_BUILD ${DEFAULT_IOS_ARMV7S_BUILD} CACHE PATH
-  "Directory containing ARMv7s iOS build to include in universal binaries (default: ${DEFAULT_IOS_ARMV7S_BUILD})")
-set(DEFAULT_IOS_ARMV8_BUILD ${CMAKE_SOURCE_DIR}/iosarmv8)
-set(IOS_ARMV8_BUILD ${DEFAULT_IOS_ARMV8_BUILD} CACHE PATH
-  "Directory containing ARMv8 iOS build to include in universal binaries (default: ${DEFAULT_IOS_ARMV8_BUILD})")
-
-configure_file(release/makemacpkg.in pkgscripts/makemacpkg)
-configure_file(release/Distribution.xml.in pkgscripts/Distribution.xml)
-configure_file(release/uninstall.in pkgscripts/uninstall)
-
-add_custom_target(dmg sh pkgscripts/makemacpkg
-  SOURCES pkgscripts/makemacpkg)
-
-add_custom_target(udmg sh pkgscripts/makemacpkg universal
-  SOURCES pkgscripts/makemacpkg)
-
-endif() # APPLE
-
-
-###############################################################################
-# Generic
-###############################################################################
-
-add_custom_target(dist
-  COMMAND git archive --prefix=${CMAKE_PROJECT_NAME}-${VERSION}/ HEAD |
-    gzip > ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}-${VERSION}.tar.gz
-    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
-
-configure_file(release/maketarball.in pkgscripts/maketarball)
-
-add_custom_target(tarball sh pkgscripts/maketarball
-  SOURCES pkgscripts/maketarball)
-
-configure_file(release/libjpeg.pc.in pkgscripts/libjpeg.pc @ONLY)
-
-configure_file(release/libturbojpeg.pc.in pkgscripts/libturbojpeg.pc @ONLY)
diff --git a/src/third_party/libjpeg-turbo/cmakescripts/GNUInstallDirs.cmake b/src/third_party/libjpeg-turbo/cmakescripts/GNUInstallDirs.cmake
deleted file mode 100644
index ef564bb..0000000
--- a/src/third_party/libjpeg-turbo/cmakescripts/GNUInstallDirs.cmake
+++ /dev/null
@@ -1,416 +0,0 @@
-#.rst:
-# GNUInstallDirs
-# --------------
-#
-# Define GNU standard installation directories
-#
-# Provides install directory variables as defined by the
-# `GNU Coding Standards`_.
-#
-# .. _`GNU Coding Standards`: https://www.gnu.org/prep/standards/html_node/Directory-Variables.html
-#
-# Result Variables
-# ^^^^^^^^^^^^^^^^
-#
-# Inclusion of this module defines the following variables:
-#
-# ``CMAKE_INSTALL_<dir>``
-#
-#   Destination for files of a given type.  This value may be passed to
-#   the ``DESTINATION`` options of :command:`install` commands for the
-#   corresponding file type.
-#
-# ``CMAKE_INSTALL_FULL_<dir>``
-#
-#   The absolute path generated from the corresponding ``CMAKE_INSTALL_<dir>``
-#   value.  If the value is not already an absolute path, an absolute path
-#   is constructed typically by prepending the value of the
-#   :variable:`CMAKE_INSTALL_PREFIX` variable.  However, there are some
-#   `special cases`_ as documented below.
-#
-# where ``<dir>`` is one of:
-#
-# ``BINDIR``
-#   user executables (``bin``)
-# ``SBINDIR``
-#   system admin executables (``sbin``)
-# ``LIBEXECDIR``
-#   program executables (``libexec``)
-# ``SYSCONFDIR``
-#   read-only single-machine data (``etc``)
-# ``SHAREDSTATEDIR``
-#   modifiable architecture-independent data (``com``)
-# ``LOCALSTATEDIR``
-#   modifiable single-machine data (``var``)
-# ``LIBDIR``
-#   object code libraries (``lib`` or ``lib64``
-#   or ``lib/<multiarch-tuple>`` on Debian)
-# ``INCLUDEDIR``
-#   C header files (``include``)
-# ``OLDINCLUDEDIR``
-#   C header files for non-gcc (``/usr/include``)
-# ``DATAROOTDIR``
-#   read-only architecture-independent data root (``share``)
-# ``DATADIR``
-#   read-only architecture-independent data (``DATAROOTDIR``)
-# ``INFODIR``
-#   info documentation (``DATAROOTDIR/info``)
-# ``LOCALEDIR``
-#   locale-dependent data (``DATAROOTDIR/locale``)
-# ``MANDIR``
-#   man documentation (``DATAROOTDIR/man``)
-# ``DOCDIR``
-#   documentation root (``DATAROOTDIR/doc/PROJECT_NAME``)
-#
-# If the includer does not define a value the above-shown default will be
-# used and the value will appear in the cache for editing by the user.
-#
-# Special Cases
-# ^^^^^^^^^^^^^
-#
-# The following values of :variable:`CMAKE_INSTALL_PREFIX` are special:
-#
-# ``/``
-#
-#   For ``<dir>`` other than the ``SYSCONFDIR`` and ``LOCALSTATEDIR``,
-#   the value of ``CMAKE_INSTALL_<dir>`` is prefixed with ``usr/`` if
-#   it is not user-specified as an absolute path.  For example, the
-#   ``INCLUDEDIR`` value ``include`` becomes ``usr/include``.
-#   This is required by the `GNU Coding Standards`_, which state:
-#
-#     When building the complete GNU system, the prefix will be empty
-#     and ``/usr`` will be a symbolic link to ``/``.
-#
-# ``/usr``
-#
-#   For ``<dir>`` equal to ``SYSCONFDIR`` or ``LOCALSTATEDIR``, the
-#   ``CMAKE_INSTALL_FULL_<dir>`` is computed by prepending just ``/``
-#   to the value of ``CMAKE_INSTALL_<dir>`` if it is not user-specified
-#   as an absolute path.  For example, the ``SYSCONFDIR`` value ``etc``
-#   becomes ``/etc``.  This is required by the `GNU Coding Standards`_.
-#
-# ``/opt/...``
-#
-#   For ``<dir>`` equal to ``SYSCONFDIR`` or ``LOCALSTATEDIR``, the
-#   ``CMAKE_INSTALL_FULL_<dir>`` is computed by *appending* the prefix
-#   to the value of ``CMAKE_INSTALL_<dir>`` if it is not user-specified
-#   as an absolute path.  For example, the ``SYSCONFDIR`` value ``etc``
-#   becomes ``/etc/opt/...``.  This is defined by the
-#   `Filesystem Hierarchy Standard`_.
-#
-# .. _`Filesystem Hierarchy Standard`: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
-#
-# Macros
-# ^^^^^^
-#
-# .. command:: GNUInstallDirs_get_absolute_install_dir
-#
-#   ::
-#
-#     GNUInstallDirs_get_absolute_install_dir(absvar var)
-#
-#   Set the given variable ``absvar`` to the absolute path contained
-#   within the variable ``var``.  This is to allow the computation of an
-#   absolute path, accounting for all the special cases documented
-#   above.  While this macro is used to compute the various
-#   ``CMAKE_INSTALL_FULL_<dir>`` variables, it is exposed publicly to
-#   allow users who create additional path variables to also compute
-#   absolute paths where necessary, using the same logic.
-
-#=============================================================================
-# Copyright 2016 D. R. Commander
-# Copyright 2016 Dmitry Marakasov
-# Copyright 2016 Roger Leigh
-# Copyright 2015 Alex Turbov
-# Copyright 2014 Rolf Eike Beer
-# Copyright 2014 Daniele E. Domenichelli
-# Copyright 2013 Dimitri John Ledkov
-# Copyright 2011 Alex Neundorf
-# Copyright 2011 Eric NOULARD
-# Copyright 2011, 2013-2015 Kitware, Inc.
-# Copyright 2011 Nikita Krupen'ko
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# * Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-#
-# * Neither the names of Kitware, Inc., the Insight Software Consortium,
-#   nor the names of their contributors may be used to endorse or promote
-#   products derived from this software without specific prior written
-#   permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#=============================================================================
-
-# Installation directories
-#
-
-macro(GNUInstallDirs_set_install_dir var docstring)
-  # If CMAKE_INSTALL_PREFIX changes and CMAKE_INSTALL_*DIR is still set to the
-  # default value, then modify it accordingly.  This presumes that the default
-  # value may change based on the prefix.
-
-  set(_GNUInstallDirs_CMAKE_INSTALL_FORCE_${var} "")
-  if(NOT DEFINED CMAKE_INSTALL_${var})
-    set(_GNUInstallDirs_CMAKE_INSTALL_DEFAULT_${var} 1 CACHE INTERNAL
-      "CMAKE_INSTALL_${var} has default value")
-  elseif(DEFINED _GNUInstallDirs_CMAKE_INSTALL_LAST_DEFAULT_${var} AND
-    NOT "${_GNUInstallDirs_CMAKE_INSTALL_LAST_DEFAULT_${var}}" STREQUAL
-      "${CMAKE_INSTALL_DEFAULT_${var}}" AND
-    _GNUInstallDirs_CMAKE_INSTALL_DEFAULT_${var} AND
-    "${_GNUInstallDirs_CMAKE_INSTALL_LAST_${var}}" STREQUAL
-      "${CMAKE_INSTALL_${var}}")
-    set(_GNUInstallDirs_CMAKE_INSTALL_FORCE_${var} "FORCE")
-  endif()
-
-  set(CMAKE_INSTALL_${var} "${CMAKE_INSTALL_DEFAULT_${var}}" CACHE PATH
-    "${docstring} (Default: ${CMAKE_INSTALL_DEFAULT_${var}})"
-    ${_GNUInstallDirs_CMAKE_INSTALL_FORCE_${var}})
-
-  if(NOT "${CMAKE_INSTALL_${var}}" STREQUAL "${CMAKE_INSTALL_DEFAULT_${var}}")
-    unset(_GNUInstallDirs_CMAKE_INSTALL_DEFAULT_${var} CACHE)
-  endif()
-
-  # Save for next run
-  set(_GNUInstallDirs_CMAKE_INSTALL_LAST_${var} "${CMAKE_INSTALL_${var}}"
-    CACHE INTERNAL "CMAKE_INSTALL_${var} during last run")
-  set(_GNUInstallDirs_CMAKE_INSTALL_LAST_DEFAULT_${var}
-    "${CMAKE_INSTALL_DEFAULT_${var}}" CACHE INTERNAL
-    "CMAKE_INSTALL_DEFAULT_${var} during last run")
-endmacro()
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_BINDIR)
-  set(CMAKE_INSTALL_DEFAULT_BINDIR "bin")
-endif()
-GNUInstallDirs_set_install_dir(BINDIR
-  "Directory into which user executables should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_SBINDIR)
-  set(CMAKE_INSTALL_DEFAULT_SBINDIR "sbin")
-endif()
-GNUInstallDirs_set_install_dir(SBINDIR
-  "Directory into which system admin executables should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_LIBEXECDIR)
-  set(CMAKE_INSTALL_DEFAULT_LIBEXECDIR "libexec")
-endif()
-GNUInstallDirs_set_install_dir(LIBEXECDIR
-  "Directory under which executables run by other programs should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_SYSCONFDIR)
-  set(CMAKE_INSTALL_DEFAULT_SYSCONFDIR "etc")
-endif()
-GNUInstallDirs_set_install_dir(SYSCONFDIR
-  "Directory into which machine-specific read-only ASCII data and configuration files should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_SHAREDSTATEDIR)
-  set(CMAKE_INSTALL_DEFAULT_SHAREDSTATEDIR "com")
-endif()
-GNUInstallDirs_set_install_dir(SHAREDSTATEDIR
-  "Directory into which architecture-independent run-time-modifiable data files should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_LOCALSTATEDIR)
-  set(CMAKE_INSTALL_DEFAULT_LOCALSTATEDIR "var")
-endif()
-GNUInstallDirs_set_install_dir(LOCALSTATEDIR
-  "Directory into which machine-specific run-time-modifiable data files should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_LIBDIR)
-  set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib")
-  # Override this default 'lib' with 'lib64' iff:
-  #  - we are on Linux system but NOT cross-compiling
-  #  - we are NOT on debian
-  #  - we are on a 64 bits system
-  # reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
-  # For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if
-  # CMAKE_LIBRARY_ARCHITECTURE is set (which contains e.g. "i386-linux-gnu"
-  # and CMAKE_INSTALL_PREFIX is "/usr"
-  # See http://wiki.debian.org/Multiarch
-  if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$"
-      AND NOT CMAKE_CROSSCOMPILING)
-    if (EXISTS "/etc/debian_version") # is this a debian system ?
-      if(CMAKE_LIBRARY_ARCHITECTURE)
-        if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
-          set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
-        endif()
-      endif()
-    else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
-      if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
-        message(AUTHOR_WARNING
-          "Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
-          "Please enable at least one language before including GNUInstallDirs.")
-      else()
-        if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
-          set(CMAKE_INSTALL_DEFAULT_LIBDIR "lib64")
-        endif()
-      endif()
-    endif()
-  endif()
-endif()
-GNUInstallDirs_set_install_dir(LIBDIR
-  "Directory into which object files and object code libraries should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_INCLUDEDIR)
-  set(CMAKE_INSTALL_DEFAULT_INCLUDEDIR "include")
-endif()
-GNUInstallDirs_set_install_dir(INCLUDEDIR
-  "Directory into which C header files should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_OLDINCLUDEDIR)
-  set(CMAKE_INSTALL_DEFAULT_OLDINCLUDEDIR "/usr/include")
-endif()
-GNUInstallDirs_set_install_dir(OLDINCLUDEDIR
-  PATH "Directory into which C header files for non-GCC compilers should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_DATAROOTDIR)
-  set(CMAKE_INSTALL_DEFAULT_DATAROOTDIR "share")
-endif()
-GNUInstallDirs_set_install_dir(DATAROOTDIR
-  "The root of the directory tree for read-only architecture-independent data files")
-
-#-----------------------------------------------------------------------------
-# Values whose defaults are relative to DATAROOTDIR.  Store empty values in
-# the cache and store the defaults in local variables if the cache values are
-# not set explicitly.  This auto-updates the defaults as DATAROOTDIR changes.
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_DATADIR)
-  set(CMAKE_INSTALL_DEFAULT_DATADIR "<CMAKE_INSTALL_DATAROOTDIR>")
-endif()
-GNUInstallDirs_set_install_dir(DATADIR
-  "The directory under which read-only architecture-independent data files should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_INFODIR)
-  if(CMAKE_SYSTEM_NAME MATCHES "^(.*BSD|DragonFly)$")
-    set(CMAKE_INSTALL_DEFAULT_INFODIR "info")
-  else()
-    set(CMAKE_INSTALL_DEFAULT_INFODIR "<CMAKE_INSTALL_DATAROOTDIR>/info")
-  endif()
-endif()
-GNUInstallDirs_set_install_dir(INFODIR
-  "The directory into which info documentation files should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_MANDIR)
-  if(CMAKE_SYSTEM_NAME MATCHES "^(.*BSD|DragonFly)$")
-    set(CMAKE_INSTALL_DEFAULT_MANDIR "man")
-  else()
-    set(CMAKE_INSTALL_DEFAULT_MANDIR "<CMAKE_INSTALL_DATAROOTDIR>/man")
-  endif()
-endif()
-GNUInstallDirs_set_install_dir(MANDIR
-  "The directory under which man pages should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_LOCALEDIR)
-  set(CMAKE_INSTALL_DEFAULT_LOCALEDIR "<CMAKE_INSTALL_DATAROOTDIR>/locale")
-endif()
-GNUInstallDirs_set_install_dir(LOCALEDIR
-  "The directory under which locale-specific message catalogs should be installed")
-
-if(NOT DEFINED CMAKE_INSTALL_DEFAULT_DOCDIR)
-  set(CMAKE_INSTALL_DEFAULT_DOCDIR "<CMAKE_INSTALL_DATAROOTDIR>/doc/${PROJECT_NAME}")
-endif()
-GNUInstallDirs_set_install_dir(DOCDIR
-  "The directory into which documentation files (other than info files) should be installed")
-
-#-----------------------------------------------------------------------------
-
-mark_as_advanced(
-  CMAKE_INSTALL_BINDIR
-  CMAKE_INSTALL_SBINDIR
-  CMAKE_INSTALL_LIBEXECDIR
-  CMAKE_INSTALL_SYSCONFDIR
-  CMAKE_INSTALL_SHAREDSTATEDIR
-  CMAKE_INSTALL_LOCALSTATEDIR
-  CMAKE_INSTALL_LIBDIR
-  CMAKE_INSTALL_INCLUDEDIR
-  CMAKE_INSTALL_OLDINCLUDEDIR
-  CMAKE_INSTALL_DATAROOTDIR
-  CMAKE_INSTALL_DATADIR
-  CMAKE_INSTALL_INFODIR
-  CMAKE_INSTALL_LOCALEDIR
-  CMAKE_INSTALL_MANDIR
-  CMAKE_INSTALL_DOCDIR
-  )
-
-macro(GNUInstallDirs_get_absolute_install_dir absvar var)
-  string(REGEX REPLACE "[<>]" "@" ${var} "${${var}}")
-  # Handle the specific case of an empty CMAKE_INSTALL_DATAROOTDIR
-  if(NOT CMAKE_INSTALL_DATAROOTDIR AND
-    ${var} MATCHES "\@CMAKE_INSTALL_DATAROOTDIR\@/")
-    string(CONFIGURE "${${var}}" ${var} @ONLY)
-    string(REGEX REPLACE "^/" "" ${var} "${${var}}")
-  else()
-    string(CONFIGURE "${${var}}" ${var} @ONLY)
-  endif()
-  if(NOT IS_ABSOLUTE "${${var}}")
-    # Handle special cases:
-    # - CMAKE_INSTALL_PREFIX == /
-    # - CMAKE_INSTALL_PREFIX == /usr
-    # - CMAKE_INSTALL_PREFIX == /opt/...
-    if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/")
-      if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR")
-        set(${absvar} "/${${var}}")
-      else()
-        if (NOT "${${var}}" MATCHES "^usr/")
-          set(${var} "usr/${${var}}")
-        endif()
-        set(${absvar} "/${${var}}")
-      endif()
-    elseif("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
-      if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR")
-        set(${absvar} "/${${var}}")
-      else()
-        set(${absvar} "${CMAKE_INSTALL_PREFIX}/${${var}}")
-      endif()
-    elseif("${CMAKE_INSTALL_PREFIX}" MATCHES "^/opt/.*")
-      if("${dir}" STREQUAL "SYSCONFDIR" OR "${dir}" STREQUAL "LOCALSTATEDIR")
-        set(${absvar} "/${${var}}${CMAKE_INSTALL_PREFIX}")
-      else()
-        set(${absvar} "${CMAKE_INSTALL_PREFIX}/${${var}}")
-      endif()
-    else()
-      set(${absvar} "${CMAKE_INSTALL_PREFIX}/${${var}}")
-    endif()
-  else()
-    set(${absvar} "${${var}}")
-  endif()
-  string(REGEX REPLACE "/$" "" ${absvar} "${${absvar}}")
-endmacro()
-
-# Result directories
-#
-foreach(dir
-    BINDIR
-    SBINDIR
-    LIBEXECDIR
-    SYSCONFDIR
-    SHAREDSTATEDIR
-    LOCALSTATEDIR
-    LIBDIR
-    INCLUDEDIR
-    OLDINCLUDEDIR
-    DATAROOTDIR
-    DATADIR
-    INFODIR
-    LOCALEDIR
-    MANDIR
-    DOCDIR
-    )
-  GNUInstallDirs_get_absolute_install_dir(CMAKE_INSTALL_FULL_${dir} CMAKE_INSTALL_${dir})
-endforeach()
diff --git a/src/third_party/libjpeg-turbo/cmakescripts/cmake_uninstall.cmake.in b/src/third_party/libjpeg-turbo/cmakescripts/cmake_uninstall.cmake.in
deleted file mode 100644
index 6726a0d..0000000
--- a/src/third_party/libjpeg-turbo/cmakescripts/cmake_uninstall.cmake.in
+++ /dev/null
@@ -1,24 +0,0 @@
-# This code is from the CMake FAQ
-
-if (NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
-  message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_BINARY_DIR@/install_manifest.txt\"")
-endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
-
-file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
-string(REGEX REPLACE "\n" ";" files "${files}")
-list(REVERSE files)
-foreach (file ${files})
-  message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
-    if (EXISTS "$ENV{DESTDIR}${file}")
-      execute_process(
-        COMMAND "@CMAKE_COMMAND@" -E remove "$ENV{DESTDIR}${file}"
-        OUTPUT_VARIABLE rm_out
-        RESULT_VARIABLE rm_retval
-      )
-    if(NOT ${rm_retval} EQUAL 0)
-      message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
-    endif (NOT ${rm_retval} EQUAL 0)
-  else (EXISTS "$ENV{DESTDIR}${file}")
-    message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
-  endif (EXISTS "$ENV{DESTDIR}${file}")
-endforeach(file)
diff --git a/src/third_party/libjpeg-turbo/cmakescripts/testclean.cmake b/src/third_party/libjpeg-turbo/cmakescripts/testclean.cmake
deleted file mode 100644
index fc3fc25..0000000
--- a/src/third_party/libjpeg-turbo/cmakescripts/testclean.cmake
+++ /dev/null
@@ -1,41 +0,0 @@
-file(GLOB FILES
-  testout*
-  *_GRAY_*.bmp
-  *_GRAY_*.png
-  *_GRAY_*.ppm
-  *_GRAY_*.jpg
-  *_GRAY.yuv
-  *_420_*.bmp
-  *_420_*.png
-  *_420_*.ppm
-  *_420_*.jpg
-  *_420.yuv
-  *_422_*.bmp
-  *_422_*.png
-  *_422_*.ppm
-  *_422_*.jpg
-  *_422.yuv
-  *_444_*.bmp
-  *_444_*.png
-  *_444_*.ppm
-  *_444_*.jpg
-  *_444.yuv
-  *_440_*.bmp
-  *_440_*.png
-  *_440_*.ppm
-  *_440_*.jpg
-  *_440.yuv
-  *_411_*.bmp
-  *_411_*.png
-  *_411_*.ppm
-  *_411_*.jpg
-  *_411.yuv
-  tjbenchtest*.log
-  tjexampletest*.log)
-
-if(NOT FILES STREQUAL "")
-  message(STATUS "Removing test files")
-  file(REMOVE ${FILES})
-else()
-  message(STATUS "No files to remove")
-endif()
diff --git a/src/third_party/libjpeg-turbo/croptest.in b/src/third_party/libjpeg-turbo/croptest.in
new file mode 100644
index 0000000..7e3c293
--- /dev/null
+++ b/src/third_party/libjpeg-turbo/croptest.in
@@ -0,0 +1,95 @@
+#!/bin/bash
+
+set -u
+set -e
+trap onexit INT
+trap onexit TERM
+trap onexit EXIT
+
+onexit()
+{
+	if [ -d $OUTDIR ]; then
+		rm -rf $OUTDIR
+	fi
+}
+
+runme()
+{
+	echo \*\*\* $*
+	$*
+}
+
+IMAGE=vgl_6548_0026a.bmp
+WIDTH=128
+HEIGHT=95
+IMGDIR=@CMAKE_CURRENT_SOURCE_DIR@/testimages
+OUTDIR=`mktemp -d /tmp/__croptest_output.XXXXXX`
+EXEDIR=@CMAKE_CURRENT_BINARY_DIR@
+
+if [ -d $OUTDIR ]; then
+	rm -rf $OUTDIR
+fi
+mkdir -p $OUTDIR
+
+exec >$EXEDIR/croptest.log
+
+echo "============================================================"
+echo "$IMAGE ($WIDTH x $HEIGHT)"
+echo "============================================================"
+echo
+
+for PROGARG in "" -progressive; do
+
+	cp $IMGDIR/$IMAGE $OUTDIR
+	basename=`basename $IMAGE .bmp`
+	echo "------------------------------------------------------------"
+	echo "Generating test images"
+	echo "------------------------------------------------------------"
+	echo
+	runme $EXEDIR/cjpeg $PROGARG -grayscale -outfile $OUTDIR/${basename}_GRAY.jpg $IMGDIR/${basename}.bmp
+	runme $EXEDIR/cjpeg $PROGARG -sample 2x2 -outfile $OUTDIR/${basename}_420.jpg $IMGDIR/${basename}.bmp
+	runme $EXEDIR/cjpeg $PROGARG -sample 2x1 -outfile $OUTDIR/${basename}_422.jpg $IMGDIR/${basename}.bmp
+	runme $EXEDIR/cjpeg $PROGARG -sample 1x2 -outfile $OUTDIR/${basename}_440.jpg $IMGDIR/${basename}.bmp
+	runme $EXEDIR/cjpeg $PROGARG -sample 1x1 -outfile $OUTDIR/${basename}_444.jpg $IMGDIR/${basename}.bmp
+	echo
+
+	for NSARG in "" -nosmooth; do
+
+		for COLORSARG in "" "-colors 256 -dither none -onepass"; do
+
+			for Y in {0..16}; do
+
+				for H in {1..16}; do
+
+					X=$(( (Y*16)%128 ))
+					W=$(( WIDTH-X-7 ))
+					if [ $Y -le 15 ]; then
+						CROPSPEC="${W}x${H}+${X}+${Y}"
+					else
+						Y2=$(( HEIGHT-H ));
+						CROPSPEC="${W}x${H}+${X}+${Y2}"
+					fi
+
+					echo "------------------------------------------------------------"
+					echo $PROGARG $NSARG $COLORSARG -crop $CROPSPEC
+					echo "------------------------------------------------------------"
+					echo
+					for samp in GRAY 420 422 440 444; do
+						$EXEDIR/djpeg $NSARG $COLORSARG -rgb -outfile $OUTDIR/${basename}_${samp}_full.ppm $OUTDIR/${basename}_${samp}.jpg
+						convert -crop $CROPSPEC $OUTDIR/${basename}_${samp}_full.ppm $OUTDIR/${basename}_${samp}_ref.ppm
+						runme $EXEDIR/djpeg $NSARG $COLORSARG -crop $CROPSPEC -rgb -outfile $OUTDIR/${basename}_${samp}.ppm $OUTDIR/${basename}_${samp}.jpg
+						runme cmp $OUTDIR/${basename}_${samp}.ppm $OUTDIR/${basename}_${samp}_ref.ppm
+					done
+					echo
+
+				done
+
+			done
+
+		done
+
+	done
+
+done
+
+echo SUCCESS!
diff --git a/src/third_party/libjpeg-turbo/djpeg.1 b/src/third_party/libjpeg-turbo/djpeg.1
index e4204b2..31431b9 100644
--- a/src/third_party/libjpeg-turbo/djpeg.1
+++ b/src/third_party/libjpeg-turbo/djpeg.1
@@ -1,4 +1,4 @@
-.TH DJPEG 1 "13 November 2017"
+.TH DJPEG 1 "4 November 2020"
 .SH NAME
 djpeg \- decompress a JPEG file to an image file
 .SH SYNOPSIS
@@ -15,8 +15,7 @@
 .B djpeg
 decompresses the named JPEG file, or the standard input if no file is named,
 and produces an image file on the standard output.  PBMPLUS (PPM/PGM), BMP,
-GIF, Targa, or RLE (Utah Raster Toolkit) output format can be selected.
-(RLE is supported only if the URT library is available.)
+GIF, or Targa output format can be selected.
 .SH OPTIONS
 All switch names may be abbreviated; for example,
 .B \-grayscale
@@ -81,9 +80,20 @@
 format is emitted.
 .TP
 .B \-gif
-Select GIF output format.  Since GIF does not support more than 256 colors,
+Select GIF output format (LZW-compressed).  Since GIF does not support more
+than 256 colors,
 .B \-colors 256
-is assumed (unless you specify a smaller number of colors).
+is assumed (unless you specify a smaller number of colors).  If you specify
+.BR \-fast,
+the default number of colors is 216.
+.TP
+.B \-gif0
+Select GIF output format (uncompressed).  Since GIF does not support more than
+256 colors,
+.B \-colors 256
+is assumed (unless you specify a smaller number of colors).  If you specify
+.BR \-fast,
+the default number of colors is 216.
 .TP
 .B \-os2
 Select BMP output format (OS/2 1.x flavor).  8-bit colormapped format is
@@ -100,9 +110,6 @@
 .B \-grayscale
 is specified; otherwise PPM is emitted.
 .TP
-.B \-rle
-Select RLE output format.  (Requires URT library.)
-.TP
 .B \-targa
 Select Targa output format.  Grayscale format is emitted if the JPEG file is
 grayscale or if
@@ -114,32 +121,40 @@
 Switches for advanced users:
 .TP
 .B \-dct int
-Use integer DCT method (default).
+Use accurate integer DCT method (default).
 .TP
 .B \-dct fast
-Use fast integer DCT (less accurate).
-In libjpeg-turbo, the fast method is generally about 5-15% faster than the int
-method when using the x86/x86-64 SIMD extensions (results may vary with other
-SIMD implementations, or when using libjpeg-turbo without SIMD extensions.)  If
-the JPEG image was compressed using a quality level of 85 or below, then there
-should be little or no perceptible difference between the two algorithms.  When
-decompressing images that were compressed using quality levels above 85,
-however, the difference between the fast and int methods becomes more
-pronounced.  With images compressed using quality=97, for instance, the fast
-method incurs generally about a 4-6 dB loss (in PSNR) relative to the int
-method, but this can be larger for some images.  If you can avoid it, do not
-use the fast method when decompressing images that were compressed using
-quality levels above 97.  The algorithm often degenerates for such images and
-can actually produce a more lossy output image than if the JPEG image had been
-compressed using lower quality levels.
+Use less accurate integer DCT method [legacy feature].
+When the Independent JPEG Group's software was first released in 1991, the
+decompression time for a 1-megapixel JPEG image on a mainstream PC was measured
+in minutes.  Thus, the \fBfast\fR integer DCT algorithm provided noticeable
+performance benefits.  On modern CPUs running libjpeg-turbo, however, the
+decompression time for a 1-megapixel JPEG image is measured in milliseconds,
+and thus the performance benefits of the \fBfast\fR algorithm are much less
+noticeable.  On modern x86/x86-64 CPUs that support AVX2 instructions, the
+\fBfast\fR and \fBint\fR methods have similar performance.  On other types of
+CPUs, the \fBfast\fR method is generally about 5-15% faster than the \fBint\fR
+method.
+
+If the JPEG image was compressed using a quality level of 85 or below, then
+there should be little or no perceptible quality difference between the two
+algorithms.  When decompressing images that were compressed using quality
+levels above 85, however, the difference between the \fBfast\fR and \fBint\fR
+methods becomes more pronounced.  With images compressed using quality=97, for
+instance, the \fBfast\fR method incurs generally about a 4-6 dB loss in PSNR
+relative to the \fBint\fR method, but this can be larger for some images.  If
+you can avoid it, do not use the \fBfast\fR method when decompressing images
+that were compressed using quality levels above 97.  The algorithm often
+degenerates for such images and can actually produce a more lossy output image
+than if the JPEG image had been compressed using lower quality levels.
 .TP
 .B \-dct float
-Use floating-point DCT method.
-The float method is mainly a legacy feature.  It does not produce significantly
-more accurate results than the int method, and it is much slower.  The float
-method may also give different results on different machines due to varying
-roundoff behavior, whereas the integer methods should give the same results on
-all machines.
+Use floating-point DCT method [legacy feature].
+The \fBfloat\fR method does not produce significantly more accurate results
+than the \fBint\fR method, and it is much slower.  The \fBfloat\fR method may
+also give different results on different machines due to varying roundoff
+behavior, whereas the integer methods should give the same results on all
+machines.
 .TP
 .B \-dither fs
 Use Floyd-Steinberg dithering in color quantization.
@@ -190,6 +205,19 @@
 .B \-max 4m
 selects 4000000 bytes.  If more space is needed, an error will occur.
 .TP
+.BI \-maxscans " N"
+Abort if the JPEG image contains more than
+.I N
+scans.  This feature demonstrates a method by which applications can guard
+against denial-of-service attacks instigated by specially-crafted malformed
+JPEG images containing numerous scans with missing image data or image data
+consisting only of "EOB runs" (a feature of progressive JPEG images that allows
+potentially hundreds of thousands of adjoining zero-value pixels to be
+represented using only a few bytes.)  Attempting to decompress such malformed
+JPEG images can cause excessive CPU activity, since the decompressor must fully
+process each scan (even if the scan is corrupt) before it can proceed to the
+next scan.
+.TP
 .BI \-outfile " name"
 Send output image to the named file, not to standard output.
 .TP
@@ -197,6 +225,9 @@
 Load input file into memory before decompressing.  This feature was implemented
 mainly as a way of testing the in-memory source manager (jpeg_mem_src().)
 .TP
+.BI \-report
+Report decompression progress.
+.TP
 .BI \-skip " Y0,Y1"
 Decompress all rows of the JPEG image except those between Y0 and Y1
 (inclusive.)  Note that if decompression scaling is being used, then Y0 and Y1
@@ -210,6 +241,12 @@
 scaled image dimensions.  Currently this option only works with the
 PBMPLUS (PPM/PGM), GIF, and Targa output formats.
 .TP
+.BI \-strict
+Treat all warnings as fatal.  This feature also demonstrates a method by which
+applications can guard against attacks instigated by specially-crafted
+malformed JPEG images.  Enabling this option will cause the decompressor to
+abort if the JPEG image contains incomplete or corrupt image data.
+.TP
 .B \-verbose
 Enable debug printout.  More
 .BR \-v 's
@@ -253,12 +290,6 @@
 .B \-dither none
 may give acceptable results in two-pass mode, but is seldom tolerable in
 one-pass mode.
-.PP
-If you are fortunate enough to have very fast floating point hardware,
-\fB\-dct float\fR may be even faster than \fB\-dct fast\fR.  But on most
-machines \fB\-dct float\fR is slower than \fB\-dct int\fR; in this case it is
-not worth using, because its theoretical accuracy advantage is too small to be
-significant in practice.
 .SH ENVIRONMENT
 .TP
 .B JPEGMEM
@@ -287,10 +318,3 @@
 This file was modified by The libjpeg-turbo Project to include only information
 relevant to libjpeg-turbo, to wordsmith certain sections, and to describe
 features not present in libjpeg.
-.SH ISSUES
-Support for compressed GIF output files was removed in djpeg v6b due to
-concerns over the Unisys LZW patent.  Although this patent expired in 2006,
-djpeg still lacks compressed GIF support, for these historical reasons.
-(Conversion of JPEG files to GIF is usually a bad idea anyway, since GIF is a
-256-color format.)  The uncompressed GIF files that djpeg generates are larger
-than they should be, but they are readable by standard GIF decoders.
diff --git a/src/third_party/libjpeg-turbo/djpeg.c b/src/third_party/libjpeg-turbo/djpeg.c
index 920e90d..cc2eb9d 100644
--- a/src/third_party/libjpeg-turbo/djpeg.c
+++ b/src/third_party/libjpeg-turbo/djpeg.c
@@ -3,9 +3,9 @@
  *
  * This file was part of the Independent JPEG Group's software:
  * Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 2013 by Guido Vollbeding.
+ * Modified 2013-2019 by Guido Vollbeding.
  * libjpeg-turbo Modifications:
- * Copyright (C) 2010-2011, 2013-2017, D. R. Commander.
+ * Copyright (C) 2010-2011, 2013-2017, 2019-2020, D. R. Commander.
  * Copyright (C) 2015, Google, Inc.
  * For conditions of distribution and use, see the accompanying README.ijg
  * file.
@@ -68,10 +68,10 @@
 
 typedef enum {
   FMT_BMP,                      /* BMP format (Windows flavor) */
-  FMT_GIF,                      /* GIF format */
+  FMT_GIF,                      /* GIF format (LZW-compressed) */
+  FMT_GIF0,                     /* GIF format (uncompressed) */
   FMT_OS2,                      /* BMP format (OS/2 flavor) */
   FMT_PPM,                      /* PPM/PGM (PBMPLUS formats) */
-  FMT_RLE,                      /* RLE format */
   FMT_TARGA,                    /* Targa format */
   FMT_TIFF                      /* TIFF format */
 } IMAGE_FORMATS;
@@ -94,11 +94,14 @@
 
 static const char *progname;    /* program name for error messages */
 static char *icc_filename;      /* for -icc switch */
+static JDIMENSION max_scans;    /* for -maxscans switch */
 static char *outfilename;       /* for -outfile switch */
-boolean memsrc;                 /* for -memsrc switch */
+static boolean memsrc;          /* for -memsrc switch */
+static boolean report;          /* for -report switch */
 boolean skip, crop;
 JDIMENSION skip_start, skip_end;
 JDIMENSION crop_x, crop_y, crop_width, crop_height;
+static boolean strict;          /* for -strict switch */
 #define INPUT_BUF_SIZE  4096
 
 
@@ -127,8 +130,10 @@
           (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
 #endif
 #ifdef GIF_SUPPORTED
-  fprintf(stderr, "  -gif           Select GIF output format%s\n",
+  fprintf(stderr, "  -gif           Select GIF output format (LZW-compressed)%s\n",
           (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
+  fprintf(stderr, "  -gif0          Select GIF output format (uncompressed)%s\n",
+          (DEFAULT_FMT == FMT_GIF0 ? " (default)" : ""));
 #endif
 #ifdef BMP_SUPPORTED
   fprintf(stderr, "  -os2           Select BMP output format (OS/2 style)%s\n",
@@ -138,25 +143,21 @@
   fprintf(stderr, "  -pnm           Select PBMPLUS (PPM/PGM) output format%s\n",
           (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
 #endif
-#ifdef RLE_SUPPORTED
-  fprintf(stderr, "  -rle           Select Utah RLE output format%s\n",
-          (DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
-#endif
 #ifdef TARGA_SUPPORTED
   fprintf(stderr, "  -targa         Select Targa output format%s\n",
           (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
 #endif
   fprintf(stderr, "Switches for advanced users:\n");
 #ifdef DCT_ISLOW_SUPPORTED
-  fprintf(stderr, "  -dct int       Use integer DCT method%s\n",
+  fprintf(stderr, "  -dct int       Use accurate integer DCT method%s\n",
           (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
 #endif
 #ifdef DCT_IFAST_SUPPORTED
-  fprintf(stderr, "  -dct fast      Use fast integer DCT (less accurate)%s\n",
+  fprintf(stderr, "  -dct fast      Use less accurate integer DCT method [legacy feature]%s\n",
           (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
 #endif
 #ifdef DCT_FLOAT_SUPPORTED
-  fprintf(stderr, "  -dct float     Use floating-point DCT method%s\n",
+  fprintf(stderr, "  -dct float     Use floating-point DCT method [legacy feature]%s\n",
           (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
 #endif
   fprintf(stderr, "  -dither fs     Use F-S dithering (default)\n");
@@ -171,14 +172,16 @@
   fprintf(stderr, "  -onepass       Use 1-pass quantization (fast, low quality)\n");
 #endif
   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
+  fprintf(stderr, "  -maxscans N    Maximum number of scans to allow in input file\n");
   fprintf(stderr, "  -outfile name  Specify name for output file\n");
 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
   fprintf(stderr, "  -memsrc        Load input file into memory before decompressing\n");
 #endif
-
+  fprintf(stderr, "  -report        Report decompression progress\n");
   fprintf(stderr, "  -skip Y0,Y1    Decompress all rows except those between Y0 and Y1 (inclusive)\n");
   fprintf(stderr, "  -crop WxH+X+Y  Decompress only a rectangular subregion of the image\n");
   fprintf(stderr, "                 [requires PBMPLUS (PPM/PGM), GIF, or Targa output format]\n");
+  fprintf(stderr, "  -strict        Treat all warnings as fatal\n");
   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
   fprintf(stderr, "  -version       Print version information and exit\n");
   exit(EXIT_FAILURE);
@@ -203,10 +206,13 @@
   /* Set up default JPEG parameters. */
   requested_fmt = DEFAULT_FMT;  /* set default output file format */
   icc_filename = NULL;
+  max_scans = 0;
   outfilename = NULL;
   memsrc = FALSE;
+  report = FALSE;
   skip = FALSE;
   crop = FALSE;
+  strict = FALSE;
   cinfo->err->trace_level = 0;
 
   /* Scan command line options, adjust parameters */
@@ -224,7 +230,7 @@
     arg++;                      /* advance past switch marker character */
 
     if (keymatch(arg, "bmp", 1)) {
-      /* BMP output format. */
+      /* BMP output format (Windows flavor). */
       requested_fmt = FMT_BMP;
 
     } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
@@ -295,9 +301,13 @@
       cinfo->do_fancy_upsampling = FALSE;
 
     } else if (keymatch(arg, "gif", 1)) {
-      /* GIF output format. */
+      /* GIF output format (LZW-compressed). */
       requested_fmt = FMT_GIF;
 
+    } else if (keymatch(arg, "gif0", 4)) {
+      /* GIF output format (uncompressed). */
+      requested_fmt = FMT_GIF0;
+
     } else if (keymatch(arg, "grayscale", 2) ||
                keymatch(arg, "greyscale", 2)) {
       /* Force monochrome output. */
@@ -351,6 +361,12 @@
         lval *= 1000L;
       cinfo->mem->max_memory_to_use = lval * 1000L;
 
+    } else if (keymatch(arg, "maxscans", 4)) {
+      if (++argn >= argc)       /* advance to next argument */
+        usage();
+      if (sscanf(argv[argn], "%u", &max_scans) != 1)
+        usage();
+
     } else if (keymatch(arg, "nosmooth", 3)) {
       /* Suppress fancy upsampling */
       cinfo->do_fancy_upsampling = FALSE;
@@ -383,9 +399,8 @@
       /* PPM/PGM output format. */
       requested_fmt = FMT_PPM;
 
-    } else if (keymatch(arg, "rle", 1)) {
-      /* RLE output format. */
-      requested_fmt = FMT_RLE;
+    } else if (keymatch(arg, "report", 2)) {
+      report = TRUE;
 
     } else if (keymatch(arg, "scale", 2)) {
       /* Scale the output image by a fraction M/N. */
@@ -413,6 +428,9 @@
         usage();
       crop = TRUE;
 
+    } else if (keymatch(arg, "strict", 2)) {
+      strict = TRUE;
+
     } else if (keymatch(arg, "targa", 1)) {
       /* Targa output format. */
       requested_fmt = FMT_TARGA;
@@ -444,7 +462,7 @@
       ERREXIT(cinfo, JERR_CANT_SUSPEND);
   }
   datasrc->bytes_in_buffer--;
-  return GETJOCTET(*datasrc->next_input_byte++);
+  return *datasrc->next_input_byte++;
 }
 
 
@@ -499,24 +517,41 @@
 }
 
 
+METHODDEF(void)
+my_emit_message(j_common_ptr cinfo, int msg_level)
+{
+  if (msg_level < 0) {
+    /* Treat warning as fatal */
+    cinfo->err->error_exit(cinfo);
+  } else {
+    if (cinfo->err->trace_level >= msg_level)
+      cinfo->err->output_message(cinfo);
+  }
+}
+
+
 /*
  * The main program.
  */
 
 int
+#ifdef GTEST
+djpeg(int argc, char **argv)
+#else
 main(int argc, char **argv)
+#endif
 {
   struct jpeg_decompress_struct cinfo;
   struct jpeg_error_mgr jerr;
-#ifdef PROGRESS_REPORT
   struct cdjpeg_progress_mgr progress;
-#endif
   int file_index;
   djpeg_dest_ptr dest_mgr = NULL;
   FILE *input_file;
   FILE *output_file;
   unsigned char *inbuffer = NULL;
+#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
   unsigned long insize = 0;
+#endif
   JDIMENSION num_scanlines;
 
   /* On Mac, fetch a command line. */
@@ -555,6 +590,9 @@
 
   file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
 
+  if (strict)
+    jerr.emit_message = my_emit_message;
+
 #ifdef TWO_FILE_COMMANDLINE
   /* Must have either -outfile switch or explicit output file name */
   if (outfilename == NULL) {
@@ -583,7 +621,7 @@
   if (file_index < argc) {
     if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
   } else {
     /* default input file is stdin */
@@ -594,16 +632,18 @@
   if (outfilename != NULL) {
     if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
       fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
   } else {
     /* default output file is stdout */
     output_file = write_stdout();
   }
 
-#ifdef PROGRESS_REPORT
-  start_progress_monitor((j_common_ptr)&cinfo, &progress);
-#endif
+  if (report || max_scans != 0) {
+    start_progress_monitor((j_common_ptr)&cinfo, &progress);
+    progress.report = report;
+    progress.max_scans = max_scans;
+  }
 
   /* Specify data source for decompression */
 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
@@ -613,7 +653,7 @@
       inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE);
       if (inbuffer == NULL) {
         fprintf(stderr, "%s: memory allocation failure\n", progname);
-        exit(EXIT_FAILURE);
+        return EXIT_FAILURE;
       }
       nbytes = JFREAD(input_file, &inbuffer[insize], INPUT_BUF_SIZE);
       if (nbytes < INPUT_BUF_SIZE && ferror(input_file)) {
@@ -651,7 +691,10 @@
 #endif
 #ifdef GIF_SUPPORTED
   case FMT_GIF:
-    dest_mgr = jinit_write_gif(&cinfo);
+    dest_mgr = jinit_write_gif(&cinfo, TRUE);
+    break;
+  case FMT_GIF0:
+    dest_mgr = jinit_write_gif(&cinfo, FALSE);
     break;
 #endif
 #ifdef PPM_SUPPORTED
@@ -659,11 +702,6 @@
     dest_mgr = jinit_write_ppm(&cinfo);
     break;
 #endif
-#ifdef RLE_SUPPORTED
-  case FMT_RLE:
-    dest_mgr = jinit_write_rle(&cinfo);
-    break;
-#endif
 #ifdef TARGA_SUPPORTED
   case FMT_TARGA:
     dest_mgr = jinit_write_targa(&cinfo);
@@ -689,7 +727,7 @@
     if (skip_end > cinfo.output_height - 1) {
       fprintf(stderr, "%s: skip region exceeds image height %d\n", progname,
               cinfo.output_height);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
 
     /* Write output file header.  This is a hack to ensure that the destination
@@ -706,7 +744,12 @@
                                           dest_mgr->buffer_height);
       (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
     }
-    jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1);
+    if ((tmp = jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1)) !=
+        skip_end - skip_start + 1) {
+      fprintf(stderr, "%s: jpeg_skip_scanlines() returned %d rather than %d\n",
+              progname, tmp, skip_end - skip_start + 1);
+      return EXIT_FAILURE;
+    }
     while (cinfo.output_scanline < cinfo.output_height) {
       num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
                                           dest_mgr->buffer_height);
@@ -724,7 +767,7 @@
         crop_y + crop_height > cinfo.output_height) {
       fprintf(stderr, "%s: crop dimensions exceed image dimensions %d x %d\n",
               progname, cinfo.output_width, cinfo.output_height);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
 
     jpeg_crop_scanline(&cinfo, &crop_x, &crop_width);
@@ -742,13 +785,24 @@
     cinfo.output_height = tmp;
 
     /* Process data */
-    jpeg_skip_scanlines(&cinfo, crop_y);
+    if ((tmp = jpeg_skip_scanlines(&cinfo, crop_y)) != crop_y) {
+      fprintf(stderr, "%s: jpeg_skip_scanlines() returned %d rather than %d\n",
+              progname, tmp, crop_y);
+      return EXIT_FAILURE;
+    }
     while (cinfo.output_scanline < crop_y + crop_height) {
       num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
                                           dest_mgr->buffer_height);
       (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
     }
-    jpeg_skip_scanlines(&cinfo, cinfo.output_height - crop_y - crop_height);
+    if ((tmp =
+         jpeg_skip_scanlines(&cinfo,
+                             cinfo.output_height - crop_y - crop_height)) !=
+        cinfo.output_height - crop_y - crop_height) {
+      fprintf(stderr, "%s: jpeg_skip_scanlines() returned %d rather than %d\n",
+              progname, tmp, cinfo.output_height - crop_y - crop_height);
+      return EXIT_FAILURE;
+    }
 
   /* Normal full-image decompress */
   } else {
@@ -763,12 +817,11 @@
     }
   }
 
-#ifdef PROGRESS_REPORT
   /* Hack: count final pass as done in case finish_output does an extra pass.
    * The library won't have updated completed_passes.
    */
-  progress.pub.completed_passes = progress.pub.total_passes;
-#endif
+  if (report || max_scans != 0)
+    progress.pub.completed_passes = progress.pub.total_passes;
 
   if (icc_filename != NULL) {
     FILE *icc_file;
@@ -777,7 +830,7 @@
 
     if ((icc_file = fopen(icc_filename, WRITE_BINARY)) == NULL) {
       fprintf(stderr, "%s: can't open %s\n", progname, icc_filename);
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
     if (jpeg_read_icc_profile(&cinfo, &icc_profile, &icc_len)) {
       if (fwrite(icc_profile, icc_len, 1, icc_file) < 1) {
@@ -785,7 +838,7 @@
                 icc_filename);
         free(icc_profile);
         fclose(icc_file);
-        exit(EXIT_FAILURE);
+        return EXIT_FAILURE;
       }
       free(icc_profile);
       fclose(icc_file);
@@ -807,14 +860,12 @@
   if (output_file != stdout)
     fclose(output_file);
 
-#ifdef PROGRESS_REPORT
-  end_progress_monitor((j_common_ptr)&cinfo);
-#endif
+  if (report || max_scans != 0)
+    end_progress_monitor((j_common_ptr)&cinfo);
 
-  if (memsrc && inbuffer != NULL)
+  if (memsrc)
     free(inbuffer);
 
   /* All done. */
-  exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
-  return 0;                     /* suppress no-return-value warnings */
+  return (jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
 }
diff --git a/src/third_party/libjpeg-turbo/doc/html/annotated.html b/src/third_party/libjpeg-turbo/doc/html/annotated.html
deleted file mode 100644
index 50286d2..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/annotated.html
+++ /dev/null
@@ -1,104 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<meta http-equiv="X-UA-Compatible" content="IE=9"/>
-<meta name="generator" content="Doxygen 1.8.3.1"/>
-<title>TurboJPEG: Data Structures</title>
-<link href="tabs.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="jquery.js"></script>
-<script type="text/javascript" src="dynsections.js"></script>
-<link href="search/search.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="search/search.js"></script>
-<script type="text/javascript">
-  $(document).ready(function() { searchBox.OnSelectItem(0); });
-</script>
-<link href="doxygen.css" rel="stylesheet" type="text/css" />
-<link href="doxygen-extra.css" rel="stylesheet" type="text/css"/>
-</head>
-<body>
-<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
-<div id="titlearea">
-<table cellspacing="0" cellpadding="0">
- <tbody>
- <tr style="height: 56px;">
-  <td style="padding-left: 0.5em;">
-   <div id="projectname">TurboJPEG
-   &#160;<span id="projectnumber">2.0</span>
-   </div>
-  </td>
- </tr>
- </tbody>
-</table>
-</div>
-<!-- end header part -->
-<!-- Generated by Doxygen 1.8.3.1 -->
-<script type="text/javascript">
-var searchBox = new SearchBox("searchBox", "search",false,'Search');
-</script>
-  <div id="navrow1" class="tabs">
-    <ul class="tablist">
-      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
-      <li><a href="modules.html"><span>Modules</span></a></li>
-      <li class="current"><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
-      <li>
-        <div id="MSearchBox" class="MSearchBoxInactive">
-        <span class="left">
-          <img id="MSearchSelect" src="search/mag_sel.png"
-               onmouseover="return searchBox.OnSearchSelectShow()"
-               onmouseout="return searchBox.OnSearchSelectHide()"
-               alt=""/>
-          <input type="text" id="MSearchField" value="Search" accesskey="S"
-               onfocus="searchBox.OnSearchFieldFocus(true)" 
-               onblur="searchBox.OnSearchFieldFocus(false)" 
-               onkeyup="searchBox.OnSearchFieldChange(event)"/>
-          </span><span class="right">
-            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
-          </span>
-        </div>
-      </li>
-    </ul>
-  </div>
-  <div id="navrow2" class="tabs2">
-    <ul class="tablist">
-      <li class="current"><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
-      <li><a href="classes.html"><span>Data&#160;Structure&#160;Index</span></a></li>
-      <li><a href="functions.html"><span>Data&#160;Fields</span></a></li>
-    </ul>
-  </div>
-</div><!-- top -->
-<!-- window showing the filter options -->
-<div id="MSearchSelectWindow"
-     onmouseover="return searchBox.OnSearchSelectShow()"
-     onmouseout="return searchBox.OnSearchSelectHide()"
-     onkeydown="return searchBox.OnSearchSelectKey(event)">
-<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Data Structures</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Groups</a></div>
-
-<!-- iframe showing the search results (closed by default) -->
-<div id="MSearchResultsWindow">
-<iframe src="javascript:void(0)" frameborder="0" 
-        name="MSearchResults" id="MSearchResults">
-</iframe>
-</div>
-
-<div class="header">
-  <div class="headertitle">
-<div class="title">Data Structures</div>  </div>
-</div><!--header-->
-<div class="contents">
-<div class="textblock">Here are the data structures with brief descriptions:</div><div class="directory">
-<table class="directory">
-<tr id="row_0_" class="even"><td class="entry"><img src="ftv2node.png" alt="o" width="16" height="22" /><img src="ftv2cl.png" alt="C" width="24" height="22" /><a class="el" href="structtjregion.html" target="_self">tjregion</a></td><td class="desc">Cropping region</td></tr>
-<tr id="row_1_"><td class="entry"><img src="ftv2node.png" alt="o" width="16" height="22" /><img src="ftv2cl.png" alt="C" width="24" height="22" /><a class="el" href="structtjscalingfactor.html" target="_self">tjscalingfactor</a></td><td class="desc">Scaling factor</td></tr>
-<tr id="row_2_" class="even"><td class="entry"><img src="ftv2lastnode.png" alt="\" width="16" height="22" /><img src="ftv2cl.png" alt="C" width="24" height="22" /><a class="el" href="structtjtransform.html" target="_self">tjtransform</a></td><td class="desc">Lossless transform</td></tr>
-</table>
-</div><!-- directory -->
-</div><!-- contents -->
-<!-- start footer part -->
-<hr class="footer"/><address class="footer"><small>
-Generated by &#160;<a href="http://www.doxygen.org/index.html">
-<img class="footer" src="doxygen.png" alt="doxygen"/>
-</a> 1.8.3.1
-</small></address>
-</body>
-</html>
diff --git a/src/third_party/libjpeg-turbo/doc/html/bc_s.png b/src/third_party/libjpeg-turbo/doc/html/bc_s.png
deleted file mode 100644
index 224b29a..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/bc_s.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/bdwn.png b/src/third_party/libjpeg-turbo/doc/html/bdwn.png
deleted file mode 100644
index 940a0b9..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/bdwn.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/classes.html b/src/third_party/libjpeg-turbo/doc/html/classes.html
deleted file mode 100644
index 41a2811..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/classes.html
+++ /dev/null
@@ -1,106 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<meta http-equiv="X-UA-Compatible" content="IE=9"/>
-<meta name="generator" content="Doxygen 1.8.3.1"/>
-<title>TurboJPEG: Data Structure Index</title>
-<link href="tabs.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="jquery.js"></script>
-<script type="text/javascript" src="dynsections.js"></script>
-<link href="search/search.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="search/search.js"></script>
-<script type="text/javascript">
-  $(document).ready(function() { searchBox.OnSelectItem(0); });
-</script>
-<link href="doxygen.css" rel="stylesheet" type="text/css" />
-<link href="doxygen-extra.css" rel="stylesheet" type="text/css"/>
-</head>
-<body>
-<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
-<div id="titlearea">
-<table cellspacing="0" cellpadding="0">
- <tbody>
- <tr style="height: 56px;">
-  <td style="padding-left: 0.5em;">
-   <div id="projectname">TurboJPEG
-   &#160;<span id="projectnumber">2.0</span>
-   </div>
-  </td>
- </tr>
- </tbody>
-</table>
-</div>
-<!-- end header part -->
-<!-- Generated by Doxygen 1.8.3.1 -->
-<script type="text/javascript">
-var searchBox = new SearchBox("searchBox", "search",false,'Search');
-</script>
-  <div id="navrow1" class="tabs">
-    <ul class="tablist">
-      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
-      <li><a href="modules.html"><span>Modules</span></a></li>
-      <li class="current"><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
-      <li>
-        <div id="MSearchBox" class="MSearchBoxInactive">
-        <span class="left">
-          <img id="MSearchSelect" src="search/mag_sel.png"
-               onmouseover="return searchBox.OnSearchSelectShow()"
-               onmouseout="return searchBox.OnSearchSelectHide()"
-               alt=""/>
-          <input type="text" id="MSearchField" value="Search" accesskey="S"
-               onfocus="searchBox.OnSearchFieldFocus(true)" 
-               onblur="searchBox.OnSearchFieldFocus(false)" 
-               onkeyup="searchBox.OnSearchFieldChange(event)"/>
-          </span><span class="right">
-            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
-          </span>
-        </div>
-      </li>
-    </ul>
-  </div>
-  <div id="navrow2" class="tabs2">
-    <ul class="tablist">
-      <li><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
-      <li class="current"><a href="classes.html"><span>Data&#160;Structure&#160;Index</span></a></li>
-      <li><a href="functions.html"><span>Data&#160;Fields</span></a></li>
-    </ul>
-  </div>
-</div><!-- top -->
-<!-- window showing the filter options -->
-<div id="MSearchSelectWindow"
-     onmouseover="return searchBox.OnSearchSelectShow()"
-     onmouseout="return searchBox.OnSearchSelectHide()"
-     onkeydown="return searchBox.OnSearchSelectKey(event)">
-<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Data Structures</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Groups</a></div>
-
-<!-- iframe showing the search results (closed by default) -->
-<div id="MSearchResultsWindow">
-<iframe src="javascript:void(0)" frameborder="0" 
-        name="MSearchResults" id="MSearchResults">
-</iframe>
-</div>
-
-<div class="header">
-  <div class="headertitle">
-<div class="title">Data Structure Index</div>  </div>
-</div><!--header-->
-<div class="contents">
-<div class="qindex"><a class="qindex" href="#letter_T">T</a></div>
-<table style="margin: 10px; white-space: nowrap;" align="center" width="95%" border="0" cellspacing="0" cellpadding="0">
-<tr><td rowspan="2" valign="bottom"><a name="letter_T"></a><table border="0" cellspacing="0" cellpadding="0"><tr><td><div class="ah">&#160;&#160;T&#160;&#160;</div></td></tr></table>
-</td><td valign="top"><a class="el" href="structtjscalingfactor.html">tjscalingfactor</a>&#160;&#160;&#160;</td><td valign="top"><a class="el" href="structtjtransform.html">tjtransform</a>&#160;&#160;&#160;</td><td></td></tr>
-<tr><td></td><td></td><td></td></tr>
-<tr><td valign="top"><a class="el" href="structtjregion.html">tjregion</a>&#160;&#160;&#160;</td><td></td><td></td><td></td></tr>
-<tr><td></td><td></td><td></td><td></td></tr>
-</table>
-<div class="qindex"><a class="qindex" href="#letter_T">T</a></div>
-</div><!-- contents -->
-<!-- start footer part -->
-<hr class="footer"/><address class="footer"><small>
-Generated by &#160;<a href="http://www.doxygen.org/index.html">
-<img class="footer" src="doxygen.png" alt="doxygen"/>
-</a> 1.8.3.1
-</small></address>
-</body>
-</html>
diff --git a/src/third_party/libjpeg-turbo/doc/html/closed.png b/src/third_party/libjpeg-turbo/doc/html/closed.png
deleted file mode 100644
index 98cc2c9..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/closed.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/doxygen-extra.css b/src/third_party/libjpeg-turbo/doc/html/doxygen-extra.css
deleted file mode 100644
index f1bd4c2..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/doxygen-extra.css
+++ /dev/null
@@ -1,3 +0,0 @@
-code {
-	color: #4665A2;
-}
diff --git a/src/third_party/libjpeg-turbo/doc/html/doxygen.css b/src/third_party/libjpeg-turbo/doc/html/doxygen.css
deleted file mode 100644
index dabaff2..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/doxygen.css
+++ /dev/null
@@ -1,1184 +0,0 @@
-/* The standard CSS for doxygen 1.8.3.1 */
-
-body, table, div, p, dl {
-	font: 400 14px/19px Roboto,sans-serif;
-}
-
-/* @group Heading Levels */
-
-h1.groupheader {
-	font-size: 150%;
-}
-
-.title {
-	font-size: 150%;
-	font-weight: bold;
-	margin: 10px 2px;
-}
-
-h2.groupheader {
-	border-bottom: 1px solid #879ECB;
-	color: #354C7B;
-	font-size: 150%;
-	font-weight: normal;
-	margin-top: 1.75em;
-	padding-top: 8px;
-	padding-bottom: 4px;
-	width: 100%;
-}
-
-h3.groupheader {
-	font-size: 100%;
-}
-
-h1, h2, h3, h4, h5, h6 {
-	-webkit-transition: text-shadow 0.5s linear;
-	-moz-transition: text-shadow 0.5s linear;
-	-ms-transition: text-shadow 0.5s linear;
-	-o-transition: text-shadow 0.5s linear;
-	transition: text-shadow 0.5s linear;
-	margin-right: 15px;
-}
-
-h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
-	text-shadow: 0 0 15px cyan;
-}
-
-dt {
-	font-weight: bold;
-}
-
-div.multicol {
-	-moz-column-gap: 1em;
-	-webkit-column-gap: 1em;
-	-moz-column-count: 3;
-	-webkit-column-count: 3;
-}
-
-p.startli, p.startdd, p.starttd {
-	margin-top: 2px;
-}
-
-p.endli {
-	margin-bottom: 0px;
-}
-
-p.enddd {
-	margin-bottom: 4px;
-}
-
-p.endtd {
-	margin-bottom: 2px;
-}
-
-/* @end */
-
-caption {
-	font-weight: bold;
-}
-
-span.legend {
-        font-size: 70%;
-        text-align: center;
-}
-
-h3.version {
-        font-size: 90%;
-        text-align: center;
-}
-
-div.qindex, div.navtab{
-	background-color: #EBEFF6;
-	border: 1px solid #A3B4D7;
-	text-align: center;
-}
-
-div.qindex, div.navpath {
-	width: 100%;
-	line-height: 140%;
-}
-
-div.navtab {
-	margin-right: 15px;
-}
-
-/* @group Link Styling */
-
-a {
-	color: #3D578C;
-	font-weight: normal;
-	text-decoration: none;
-}
-
-.contents a:visited {
-	color: #4665A2;
-}
-
-a:hover {
-	text-decoration: underline;
-}
-
-a.qindex {
-	font-weight: bold;
-}
-
-a.qindexHL {
-	font-weight: bold;
-	background-color: #9CAFD4;
-	color: #ffffff;
-	border: 1px double #869DCA;
-}
-
-.contents a.qindexHL:visited {
-        color: #ffffff;
-}
-
-a.el {
-	font-weight: bold;
-}
-
-a.elRef {
-}
-
-a.code, a.code:visited {
-	color: #4665A2; 
-}
-
-a.codeRef, a.codeRef:visited {
-	color: #4665A2; 
-}
-
-/* @end */
-
-dl.el {
-	margin-left: -1cm;
-}
-
-pre.fragment {
-        border: 1px solid #C4CFE5;
-        background-color: #FBFCFD;
-        padding: 4px 6px;
-        margin: 4px 8px 4px 2px;
-        overflow: auto;
-        word-wrap: break-word;
-        font-size:  9pt;
-        line-height: 125%;
-        font-family: monospace, fixed;
-        font-size: 105%;
-}
-
-div.fragment {
-        padding: 4px;
-        margin: 4px;
-	background-color: #FBFCFD;
-	border: 1px solid #C4CFE5;
-}
-
-div.line {
-	font-family: monospace, fixed;
-        font-size: 13px;
-	min-height: 13px;
-	line-height: 1.0;
-	text-wrap: unrestricted;
-	white-space: -moz-pre-wrap; /* Moz */
-	white-space: -pre-wrap;     /* Opera 4-6 */
-	white-space: -o-pre-wrap;   /* Opera 7 */
-	white-space: pre-wrap;      /* CSS3  */
-	word-wrap: break-word;      /* IE 5.5+ */
-	text-indent: -53px;
-	padding-left: 53px;
-	padding-bottom: 0px;
-	margin: 0px;
-	-webkit-transition-property: background-color, box-shadow;
-	-webkit-transition-duration: 0.5s;
-	-moz-transition-property: background-color, box-shadow;
-	-moz-transition-duration: 0.5s;
-	-ms-transition-property: background-color, box-shadow;
-	-ms-transition-duration: 0.5s;
-	-o-transition-property: background-color, box-shadow;
-	-o-transition-duration: 0.5s;
-	transition-property: background-color, box-shadow;
-	transition-duration: 0.5s;
-}
-
-div.line.glow {
-	background-color: cyan;
-	box-shadow: 0 0 10px cyan;
-}
-
-
-span.lineno {
-	padding-right: 4px;
-	text-align: right;
-	border-right: 2px solid #0F0;
-	background-color: #E8E8E8;
-        white-space: pre;
-}
-span.lineno a {
-	background-color: #D8D8D8;
-}
-
-span.lineno a:hover {
-	background-color: #C8C8C8;
-}
-
-div.ah {
-	background-color: black;
-	font-weight: bold;
-	color: #ffffff;
-	margin-bottom: 3px;
-	margin-top: 3px;
-	padding: 0.2em;
-	border: solid thin #333;
-	border-radius: 0.5em;
-	-webkit-border-radius: .5em;
-	-moz-border-radius: .5em;
-	box-shadow: 2px 2px 3px #999;
-	-webkit-box-shadow: 2px 2px 3px #999;
-	-moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
-	background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
-	background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000);
-}
-
-div.groupHeader {
-	margin-left: 16px;
-	margin-top: 12px;
-	font-weight: bold;
-}
-
-div.groupText {
-	margin-left: 16px;
-	font-style: italic;
-}
-
-body {
-	background-color: white;
-	color: black;
-        margin: 0;
-}
-
-div.contents {
-	margin-top: 10px;
-	margin-left: 12px;
-	margin-right: 8px;
-}
-
-td.indexkey {
-	background-color: #EBEFF6;
-	font-weight: bold;
-	border: 1px solid #C4CFE5;
-	margin: 2px 0px 2px 0;
-	padding: 2px 10px;
-        white-space: nowrap;
-        vertical-align: top;
-}
-
-td.indexvalue {
-	background-color: #EBEFF6;
-	border: 1px solid #C4CFE5;
-	padding: 2px 10px;
-	margin: 2px 0px;
-}
-
-tr.memlist {
-	background-color: #EEF1F7;
-}
-
-p.formulaDsp {
-	text-align: center;
-}
-
-img.formulaDsp {
-	
-}
-
-img.formulaInl {
-	vertical-align: middle;
-}
-
-div.center {
-	text-align: center;
-        margin-top: 0px;
-        margin-bottom: 0px;
-        padding: 0px;
-}
-
-div.center img {
-	border: 0px;
-}
-
-address.footer {
-	text-align: right;
-	padding-right: 12px;
-}
-
-img.footer {
-	border: 0px;
-	vertical-align: middle;
-}
-
-/* @group Code Colorization */
-
-span.keyword {
-	color: #008000
-}
-
-span.keywordtype {
-	color: #604020
-}
-
-span.keywordflow {
-	color: #e08000
-}
-
-span.comment {
-	color: #800000
-}
-
-span.preprocessor {
-	color: #806020
-}
-
-span.stringliteral {
-	color: #002080
-}
-
-span.charliteral {
-	color: #008080
-}
-
-span.vhdldigit { 
-	color: #ff00ff 
-}
-
-span.vhdlchar { 
-	color: #000000 
-}
-
-span.vhdlkeyword { 
-	color: #700070 
-}
-
-span.vhdllogic { 
-	color: #ff0000 
-}
-
-blockquote {
-        background-color: #F7F8FB;
-        border-left: 2px solid #9CAFD4;
-        margin: 0 24px 0 4px;
-        padding: 0 12px 0 16px;
-}
-
-/* @end */
-
-/*
-.search {
-	color: #003399;
-	font-weight: bold;
-}
-
-form.search {
-	margin-bottom: 0px;
-	margin-top: 0px;
-}
-
-input.search {
-	font-size: 75%;
-	color: #000080;
-	font-weight: normal;
-	background-color: #e8eef2;
-}
-*/
-
-td.tiny {
-	font-size: 75%;
-}
-
-.dirtab {
-	padding: 4px;
-	border-collapse: collapse;
-	border: 1px solid #A3B4D7;
-}
-
-th.dirtab {
-	background: #EBEFF6;
-	font-weight: bold;
-}
-
-hr {
-	height: 0px;
-	border: none;
-	border-top: 1px solid #4A6AAA;
-}
-
-hr.footer {
-	height: 1px;
-}
-
-/* @group Member Descriptions */
-
-table.memberdecls {
-	border-spacing: 0px;
-	padding: 0px;
-}
-
-.memberdecls td, .fieldtable tr {
-	-webkit-transition-property: background-color, box-shadow;
-	-webkit-transition-duration: 0.5s;
-	-moz-transition-property: background-color, box-shadow;
-	-moz-transition-duration: 0.5s;
-	-ms-transition-property: background-color, box-shadow;
-	-ms-transition-duration: 0.5s;
-	-o-transition-property: background-color, box-shadow;
-	-o-transition-duration: 0.5s;
-	transition-property: background-color, box-shadow;
-	transition-duration: 0.5s;
-}
-
-.memberdecls td.glow, .fieldtable tr.glow {
-	background-color: cyan;
-	box-shadow: 0 0 15px cyan;
-}
-
-.mdescLeft, .mdescRight,
-.memItemLeft, .memItemRight,
-.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
-	background-color: #F9FAFC;
-	border: none;
-	margin: 4px;
-	padding: 1px 0 0 8px;
-}
-
-.mdescLeft, .mdescRight {
-	padding: 0px 8px 4px 8px;
-	color: #555;
-}
-
-.memSeparator {
-        border-bottom: 1px solid #DEE4F0;
-        line-height: 1px;
-        margin: 0px;
-        padding: 0px;
-}
-
-.memItemLeft, .memTemplItemLeft {
-        white-space: nowrap;
-}
-
-.memItemRight {
-	width: 100%;
-}
-
-.memTemplParams {
-	color: #4665A2;
-        white-space: nowrap;
-	font-size: 80%;
-}
-
-/* @end */
-
-/* @group Member Details */
-
-/* Styles for detailed member documentation */
-
-.memtemplate {
-	font-size: 80%;
-	color: #4665A2;
-	font-weight: normal;
-	margin-left: 9px;
-}
-
-.memnav {
-	background-color: #EBEFF6;
-	border: 1px solid #A3B4D7;
-	text-align: center;
-	margin: 2px;
-	margin-right: 15px;
-	padding: 2px;
-}
-
-.mempage {
-	width: 100%;
-}
-
-.memitem {
-	padding: 0;
-	margin-bottom: 10px;
-	margin-right: 5px;
-        -webkit-transition: box-shadow 0.5s linear;
-        -moz-transition: box-shadow 0.5s linear;
-        -ms-transition: box-shadow 0.5s linear;
-        -o-transition: box-shadow 0.5s linear;
-        transition: box-shadow 0.5s linear;
-        display: table !important;
-        width: 100%;
-}
-
-.memitem.glow {
-         box-shadow: 0 0 15px cyan;
-}
-
-.memname {
-        font-weight: bold;
-        margin-left: 6px;
-}
-
-.memname td {
-	vertical-align: bottom;
-}
-
-.memproto, dl.reflist dt {
-        border-top: 1px solid #A8B8D9;
-        border-left: 1px solid #A8B8D9;
-        border-right: 1px solid #A8B8D9;
-        padding: 6px 0px 6px 0px;
-        color: #253555;
-        font-weight: bold;
-        text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
-        background-image:url('nav_f.png');
-        background-repeat:repeat-x;
-        background-color: #E2E8F2;
-        /* opera specific markup */
-        box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
-        border-top-right-radius: 4px;
-        border-top-left-radius: 4px;
-        /* firefox specific markup */
-        -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
-        -moz-border-radius-topright: 4px;
-        -moz-border-radius-topleft: 4px;
-        /* webkit specific markup */
-        -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
-        -webkit-border-top-right-radius: 4px;
-        -webkit-border-top-left-radius: 4px;
-
-}
-
-.memdoc, dl.reflist dd {
-        border-bottom: 1px solid #A8B8D9;      
-        border-left: 1px solid #A8B8D9;      
-        border-right: 1px solid #A8B8D9; 
-        padding: 6px 10px 2px 10px;
-        background-color: #FBFCFD;
-        border-top-width: 0;
-        background-image:url('nav_g.png');
-        background-repeat:repeat-x;
-        background-color: #FFFFFF;
-        /* opera specific markup */
-        border-bottom-left-radius: 4px;
-        border-bottom-right-radius: 4px;
-        box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
-        /* firefox specific markup */
-        -moz-border-radius-bottomleft: 4px;
-        -moz-border-radius-bottomright: 4px;
-        -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
-        /* webkit specific markup */
-        -webkit-border-bottom-left-radius: 4px;
-        -webkit-border-bottom-right-radius: 4px;
-        -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
-}
-
-dl.reflist dt {
-        padding: 5px;
-}
-
-dl.reflist dd {
-        margin: 0px 0px 10px 0px;
-        padding: 5px;
-}
-
-.paramkey {
-	text-align: right;
-}
-
-.paramtype {
-	white-space: nowrap;
-}
-
-.paramname {
-	color: #602020;
-	white-space: nowrap;
-}
-.paramname em {
-	font-style: normal;
-}
-.paramname code {
-        line-height: 14px;
-}
-
-.params, .retval, .exception, .tparams {
-        margin-left: 0px;
-        padding-left: 0px;
-}       
-
-.params .paramname, .retval .paramname {
-        font-weight: bold;
-        vertical-align: top;
-}
-        
-.params .paramtype {
-        font-style: italic;
-        vertical-align: top;
-}       
-        
-.params .paramdir {
-        font-family: "courier new",courier,monospace;
-        vertical-align: top;
-}
-
-table.mlabels {
-	border-spacing: 0px;
-}
-
-td.mlabels-left {
-	width: 100%;
-	padding: 0px;
-}
-
-td.mlabels-right {
-	vertical-align: bottom;
-	padding: 0px;
-	white-space: nowrap;
-}
-
-span.mlabels {
-        margin-left: 8px;
-}
-
-span.mlabel {
-        background-color: #728DC1;
-        border-top:1px solid #5373B4;
-        border-left:1px solid #5373B4;
-        border-right:1px solid #C4CFE5;
-        border-bottom:1px solid #C4CFE5;
-	text-shadow: none;
-	color: white;
-	margin-right: 4px;
-	padding: 2px 3px;
-	border-radius: 3px;
-	font-size: 7pt;
-	white-space: nowrap;
-	vertical-align: middle;
-}
-
-
-
-/* @end */
-
-/* these are for tree view when not used as main index */
-
-div.directory {
-        margin: 10px 0px;
-        border-top: 1px solid #A8B8D9;
-        border-bottom: 1px solid #A8B8D9;
-        width: 100%;
-}
-
-.directory table {
-        border-collapse:collapse;
-}
-
-.directory td {
-        margin: 0px;
-        padding: 0px;
-	vertical-align: top;
-}
-
-.directory td.entry {
-        white-space: nowrap;
-        padding-right: 6px;
-}
-
-.directory td.entry a {
-        outline:none;
-}
-
-.directory td.entry a img {
-        border: none;
-}
-
-.directory td.desc {
-        width: 100%;
-        padding-left: 6px;
-	padding-right: 6px;
-	padding-top: 3px;
-	border-left: 1px solid rgba(0,0,0,0.05);
-}
-
-.directory tr.even {
-	padding-left: 6px;
-	background-color: #F7F8FB;
-}
-
-.directory img {
-	vertical-align: -30%;
-}
-
-.directory .levels {
-        white-space: nowrap;
-        width: 100%;
-        text-align: right;
-        font-size: 9pt;
-}
-
-.directory .levels span {
-        cursor: pointer;
-        padding-left: 2px;
-        padding-right: 2px;
-	color: #3D578C;
-}
-
-div.dynheader {
-        margin-top: 8px;
-	-webkit-touch-callout: none;
-	-webkit-user-select: none;
-	-khtml-user-select: none;
-	-moz-user-select: none;
-	-ms-user-select: none;
-	user-select: none;
-}
-
-address {
-	font-style: normal;
-	color: #2A3D61;
-}
-
-table.doxtable {
-	border-collapse:collapse;
-        margin-top: 4px;
-        margin-bottom: 4px;
-}
-
-table.doxtable td, table.doxtable th {
-	border: 1px solid #2D4068;
-	padding: 3px 7px 2px;
-}
-
-table.doxtable th {
-	background-color: #374F7F;
-	color: #FFFFFF;
-	font-size: 110%;
-	padding-bottom: 4px;
-	padding-top: 5px;
-}
-
-table.fieldtable {
-        /*width: 100%;*/
-        margin-bottom: 10px;
-        border: 1px solid #A8B8D9;
-        border-spacing: 0px;
-        -moz-border-radius: 4px;
-        -webkit-border-radius: 4px;
-        border-radius: 4px;
-        -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
-        -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
-        box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
-}
-
-.fieldtable td, .fieldtable th {
-        padding: 3px 7px 2px;
-}
-
-.fieldtable td.fieldtype, .fieldtable td.fieldname {
-        white-space: nowrap;
-        border-right: 1px solid #A8B8D9;
-        border-bottom: 1px solid #A8B8D9;
-        vertical-align: top;
-}
-
-.fieldtable td.fieldname {
-        padding-top: 5px;
-}
-
-.fieldtable td.fielddoc {
-        border-bottom: 1px solid #A8B8D9;
-        /*width: 100%;*/
-}
-
-.fieldtable td.fielddoc p:first-child {
-        margin-top: 2px;
-}       
-        
-.fieldtable td.fielddoc p:last-child {
-        margin-bottom: 2px;
-}
-
-.fieldtable tr:last-child td {
-        border-bottom: none;
-}
-
-.fieldtable th {
-        background-image:url('nav_f.png');
-        background-repeat:repeat-x;
-        background-color: #E2E8F2;
-        font-size: 90%;
-        color: #253555;
-        padding-bottom: 4px;
-        padding-top: 5px;
-        text-align:left;
-        -moz-border-radius-topleft: 4px;
-        -moz-border-radius-topright: 4px;
-        -webkit-border-top-left-radius: 4px;
-        -webkit-border-top-right-radius: 4px;
-        border-top-left-radius: 4px;
-        border-top-right-radius: 4px;
-        border-bottom: 1px solid #A8B8D9;
-}
-
-
-.tabsearch {
-	top: 0px;
-	left: 10px;
-	height: 36px;
-	background-image: url('tab_b.png');
-	z-index: 101;
-	overflow: hidden;
-	font-size: 13px;
-}
-
-.navpath ul
-{
-	font-size: 11px;
-	background-image:url('tab_b.png');
-	background-repeat:repeat-x;
-	background-position: 0 -5px;
-	height:30px;
-	line-height:30px;
-	color:#8AA0CC;
-	border:solid 1px #C2CDE4;
-	overflow:hidden;
-	margin:0px;
-	padding:0px;
-}
-
-.navpath li
-{
-	list-style-type:none;
-	float:left;
-	padding-left:10px;
-	padding-right:15px;
-	background-image:url('bc_s.png');
-	background-repeat:no-repeat;
-	background-position:right;
-	color:#364D7C;
-}
-
-.navpath li.navelem a
-{
-	height:32px;
-	display:block;
-	text-decoration: none;
-	outline: none;
-	color: #283A5D;
-	font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
-	text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
-	text-decoration: none;        
-}
-
-.navpath li.navelem a:hover
-{
-	color:#6884BD;
-}
-
-.navpath li.footer
-{
-        list-style-type:none;
-        float:right;
-        padding-left:10px;
-        padding-right:15px;
-        background-image:none;
-        background-repeat:no-repeat;
-        background-position:right;
-        color:#364D7C;
-        font-size: 8pt;
-}
-
-
-div.summary
-{
-	float: right;
-	font-size: 8pt;
-	padding-right: 5px;
-	width: 50%;
-	text-align: right;
-}       
-
-div.summary a
-{
-	white-space: nowrap;
-}
-
-div.ingroups
-{
-	font-size: 8pt;
-	width: 50%;
-	text-align: left;
-}
-
-div.ingroups a
-{
-	white-space: nowrap;
-}
-
-div.header
-{
-        background-image:url('nav_h.png');
-        background-repeat:repeat-x;
-	background-color: #F9FAFC;
-	margin:  0px;
-	border-bottom: 1px solid #C4CFE5;
-}
-
-div.headertitle
-{
-	padding: 5px 5px 5px 10px;
-}
-
-dl
-{
-        padding: 0 0 0 10px;
-}
-
-/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */
-dl.section
-{
-	margin-left: 0px;
-	padding-left: 0px;
-}
-
-dl.note
-{
-        margin-left:-7px;
-        padding-left: 3px;
-        border-left:4px solid;
-        border-color: #D0C000;
-}
-
-dl.warning, dl.attention
-{
-        margin-left:-7px;
-        padding-left: 3px;
-        border-left:4px solid;
-        border-color: #FF0000;
-}
-
-dl.pre, dl.post, dl.invariant
-{
-        margin-left:-7px;
-        padding-left: 3px;
-        border-left:4px solid;
-        border-color: #00D000;
-}
-
-dl.deprecated
-{
-        margin-left:-7px;
-        padding-left: 3px;
-        border-left:4px solid;
-        border-color: #505050;
-}
-
-dl.todo
-{
-        margin-left:-7px;
-        padding-left: 3px;
-        border-left:4px solid;
-        border-color: #00C0E0;
-}
-
-dl.test
-{
-        margin-left:-7px;
-        padding-left: 3px;
-        border-left:4px solid;
-        border-color: #3030E0;
-}
-
-dl.bug
-{
-        margin-left:-7px;
-        padding-left: 3px;
-        border-left:4px solid;
-        border-color: #C08050;
-}
-
-dl.section dd {
-	margin-bottom: 6px;
-}
-
-
-#projectlogo
-{
-	text-align: center;
-	vertical-align: bottom;
-	border-collapse: separate;
-}
- 
-#projectlogo img
-{ 
-	border: 0px none;
-}
- 
-#projectname
-{
-	font: 300% Tahoma, Arial,sans-serif;
-	margin: 0px;
-	padding: 2px 0px;
-}
-    
-#projectbrief
-{
-	font: 120% Tahoma, Arial,sans-serif;
-	margin: 0px;
-	padding: 0px;
-}
-
-#projectnumber
-{
-	font: 50% Tahoma, Arial,sans-serif;
-	margin: 0px;
-	padding: 0px;
-}
-
-#titlearea
-{
-	padding: 0px;
-	margin: 0px;
-	width: 100%;
-	border-bottom: 1px solid #5373B4;
-}
-
-.image
-{
-        text-align: center;
-}
-
-.dotgraph
-{
-        text-align: center;
-}
-
-.mscgraph
-{
-        text-align: center;
-}
-
-.caption
-{
-	font-weight: bold;
-}
-
-div.zoom
-{
-	border: 1px solid #90A5CE;
-}
-
-dl.citelist {
-        margin-bottom:50px;
-}
-
-dl.citelist dt {
-        color:#334975;
-        float:left;
-        font-weight:bold;
-        margin-right:10px;
-        padding:5px;
-}
-
-dl.citelist dd {
-        margin:2px 0;
-        padding:5px 0;
-}
-
-div.toc {
-        padding: 14px 25px;
-        background-color: #F4F6FA;
-        border: 1px solid #D8DFEE;
-        border-radius: 7px 7px 7px 7px;
-        float: right;
-        height: auto;
-        margin: 0 20px 10px 10px;
-        width: 200px;
-}
-
-div.toc li {
-        background: url("bdwn.png") no-repeat scroll 0 5px transparent;
-        font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;
-        margin-top: 5px;
-        padding-left: 10px;
-        padding-top: 2px;
-}
-
-div.toc h3 {
-        font: bold 12px/1.2 Arial,FreeSans,sans-serif;
-	color: #4665A2;
-        border-bottom: 0 none;
-        margin: 0;
-}
-
-div.toc ul {
-        list-style: none outside none;
-        border: medium none;
-        padding: 0px;
-}       
-
-div.toc li.level1 {
-        margin-left: 0px;
-}
-
-div.toc li.level2 {
-        margin-left: 15px;
-}
-
-div.toc li.level3 {
-        margin-left: 30px;
-}
-
-div.toc li.level4 {
-        margin-left: 45px;
-}
-
-.inherit_header {
-        font-weight: bold;
-        color: gray;
-        cursor: pointer;
-	-webkit-touch-callout: none;
-	-webkit-user-select: none;
-	-khtml-user-select: none;
-	-moz-user-select: none;
-	-ms-user-select: none;
-	user-select: none;
-}
-
-.inherit_header td {
-        padding: 6px 0px 2px 5px;
-}
-
-.inherit {
-        display: none;
-}
-
-tr.heading h2 {
-        margin-top: 12px;
-        margin-bottom: 4px;
-}
-
-@media print
-{
-  #top { display: none; }
-  #side-nav { display: none; }
-  #nav-path { display: none; }
-  body { overflow:visible; }
-  h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
-  .summary { display: none; }
-  .memitem { page-break-inside: avoid; }
-  #doc-content
-  {
-    margin-left:0 !important;
-    height:auto !important;
-    width:auto !important;
-    overflow:inherit;
-    display:inline;
-  }
-}
-
diff --git a/src/third_party/libjpeg-turbo/doc/html/doxygen.png b/src/third_party/libjpeg-turbo/doc/html/doxygen.png
deleted file mode 100644
index 3ff17d8..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/doxygen.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/dynsections.js b/src/third_party/libjpeg-turbo/doc/html/dynsections.js
deleted file mode 100644
index ed092c7..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/dynsections.js
+++ /dev/null
@@ -1,97 +0,0 @@
-function toggleVisibility(linkObj)
-{
- var base = $(linkObj).attr('id');
- var summary = $('#'+base+'-summary');
- var content = $('#'+base+'-content');
- var trigger = $('#'+base+'-trigger');
- var src=$(trigger).attr('src');
- if (content.is(':visible')===true) {
-   content.hide();
-   summary.show();
-   $(linkObj).addClass('closed').removeClass('opened');
-   $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png');
- } else {
-   content.show();
-   summary.hide();
-   $(linkObj).removeClass('closed').addClass('opened');
-   $(trigger).attr('src',src.substring(0,src.length-10)+'open.png');
- } 
- return false;
-}
-
-function updateStripes()
-{
-  $('table.directory tr').
-       removeClass('even').filter(':visible:even').addClass('even');
-}
-function toggleLevel(level)
-{
-  $('table.directory tr').each(function(){ 
-    var l = this.id.split('_').length-1;
-    var i = $('#img'+this.id.substring(3));
-    var a = $('#arr'+this.id.substring(3));
-    if (l<level+1) {
-      i.attr('src','ftv2folderopen.png');
-      a.attr('src','ftv2mnode.png');
-      $(this).show();
-    } else if (l==level+1) {
-      i.attr('src','ftv2folderclosed.png');
-      a.attr('src','ftv2pnode.png');
-      $(this).show();
-    } else {
-      $(this).hide();
-    }
-  });
-  updateStripes();
-}
-
-function toggleFolder(id)
-{
-  //The clicked row
-  var currentRow = $('#row_'+id);
-  var currentRowImages = currentRow.find("img");
-
-  //All rows after the clicked row
-  var rows = currentRow.nextAll("tr");
-
-  //Only match elements AFTER this one (can't hide elements before)
-  var childRows = rows.filter(function() {
-    var re = new RegExp('^row_'+id+'\\d+_$', "i"); //only one sub
-    return this.id.match(re);
-  });
-
-  //First row is visible we are HIDING
-  if (childRows.filter(':first').is(':visible')===true) {
-    currentRowImages.filter("[id^=arr]").attr('src', 'ftv2pnode.png');
-    currentRowImages.filter("[id^=img]").attr('src', 'ftv2folderclosed.png');
-    rows.filter("[id^=row_"+id+"]").hide();
-  } else { //We are SHOWING
-    //All sub images
-    var childImages = childRows.find("img");
-    var childImg = childImages.filter("[id^=img]");
-    var childArr = childImages.filter("[id^=arr]");
-
-    currentRow.find("[id^=arr]").attr('src', 'ftv2mnode.png'); //open row
-    currentRow.find("[id^=img]").attr('src', 'ftv2folderopen.png'); //open row
-    childImg.attr('src','ftv2folderclosed.png'); //children closed
-    childArr.attr('src','ftv2pnode.png'); //children closed
-    childRows.show(); //show all children
-  }
-  updateStripes();
-}
-
-
-function toggleInherit(id)
-{
-  var rows = $('tr.inherit.'+id);
-  var img = $('tr.inherit_header.'+id+' img');
-  var src = $(img).attr('src');
-  if (rows.filter(':first').is(':visible')===true) {
-    rows.css('display','none');
-    $(img).attr('src',src.substring(0,src.length-8)+'closed.png');
-  } else {
-    rows.css('display','table-row'); // using show() causes jump in firefox
-    $(img).attr('src',src.substring(0,src.length-10)+'open.png');
-  }
-}
-
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2blank.png b/src/third_party/libjpeg-turbo/doc/html/ftv2blank.png
deleted file mode 100644
index 63c605b..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2blank.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2cl.png b/src/third_party/libjpeg-turbo/doc/html/ftv2cl.png
deleted file mode 100644
index 132f657..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2cl.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2doc.png b/src/third_party/libjpeg-turbo/doc/html/ftv2doc.png
deleted file mode 100644
index 17edabf..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2doc.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2folderclosed.png b/src/third_party/libjpeg-turbo/doc/html/ftv2folderclosed.png
deleted file mode 100644
index bb8ab35..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2folderclosed.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2folderopen.png b/src/third_party/libjpeg-turbo/doc/html/ftv2folderopen.png
deleted file mode 100644
index d6c7f67..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2folderopen.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2lastnode.png b/src/third_party/libjpeg-turbo/doc/html/ftv2lastnode.png
deleted file mode 100644
index 63c605b..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2lastnode.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2link.png b/src/third_party/libjpeg-turbo/doc/html/ftv2link.png
deleted file mode 100644
index 17edabf..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2link.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2mlastnode.png b/src/third_party/libjpeg-turbo/doc/html/ftv2mlastnode.png
deleted file mode 100644
index 0b63f6d..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2mlastnode.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2mnode.png b/src/third_party/libjpeg-turbo/doc/html/ftv2mnode.png
deleted file mode 100644
index 0b63f6d..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2mnode.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2mo.png b/src/third_party/libjpeg-turbo/doc/html/ftv2mo.png
deleted file mode 100644
index 4bfb80f..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2mo.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2node.png b/src/third_party/libjpeg-turbo/doc/html/ftv2node.png
deleted file mode 100644
index 63c605b..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2node.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2ns.png b/src/third_party/libjpeg-turbo/doc/html/ftv2ns.png
deleted file mode 100644
index 72e3d71..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2ns.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2plastnode.png b/src/third_party/libjpeg-turbo/doc/html/ftv2plastnode.png
deleted file mode 100644
index c6ee22f..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2plastnode.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2pnode.png b/src/third_party/libjpeg-turbo/doc/html/ftv2pnode.png
deleted file mode 100644
index c6ee22f..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2pnode.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2splitbar.png b/src/third_party/libjpeg-turbo/doc/html/ftv2splitbar.png
deleted file mode 100644
index fe895f2..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2splitbar.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/ftv2vertline.png b/src/third_party/libjpeg-turbo/doc/html/ftv2vertline.png
deleted file mode 100644
index 63c605b..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/ftv2vertline.png
+++ /dev/null
Binary files differ
diff --git a/src/third_party/libjpeg-turbo/doc/html/functions.html b/src/third_party/libjpeg-turbo/doc/html/functions.html
deleted file mode 100644
index 1042ae7..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/functions.html
+++ /dev/null
@@ -1,134 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<meta http-equiv="X-UA-Compatible" content="IE=9"/>
-<meta name="generator" content="Doxygen 1.8.3.1"/>
-<title>TurboJPEG: Data Fields</title>
-<link href="tabs.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="jquery.js"></script>
-<script type="text/javascript" src="dynsections.js"></script>
-<link href="search/search.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="search/search.js"></script>
-<script type="text/javascript">
-  $(document).ready(function() { searchBox.OnSelectItem(0); });
-</script>
-<link href="doxygen.css" rel="stylesheet" type="text/css" />
-<link href="doxygen-extra.css" rel="stylesheet" type="text/css"/>
-</head>
-<body>
-<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
-<div id="titlearea">
-<table cellspacing="0" cellpadding="0">
- <tbody>
- <tr style="height: 56px;">
-  <td style="padding-left: 0.5em;">
-   <div id="projectname">TurboJPEG
-   &#160;<span id="projectnumber">2.0</span>
-   </div>
-  </td>
- </tr>
- </tbody>
-</table>
-</div>
-<!-- end header part -->
-<!-- Generated by Doxygen 1.8.3.1 -->
-<script type="text/javascript">
-var searchBox = new SearchBox("searchBox", "search",false,'Search');
-</script>
-  <div id="navrow1" class="tabs">
-    <ul class="tablist">
-      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
-      <li><a href="modules.html"><span>Modules</span></a></li>
-      <li class="current"><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
-      <li>
-        <div id="MSearchBox" class="MSearchBoxInactive">
-        <span class="left">
-          <img id="MSearchSelect" src="search/mag_sel.png"
-               onmouseover="return searchBox.OnSearchSelectShow()"
-               onmouseout="return searchBox.OnSearchSelectHide()"
-               alt=""/>
-          <input type="text" id="MSearchField" value="Search" accesskey="S"
-               onfocus="searchBox.OnSearchFieldFocus(true)" 
-               onblur="searchBox.OnSearchFieldFocus(false)" 
-               onkeyup="searchBox.OnSearchFieldChange(event)"/>
-          </span><span class="right">
-            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
-          </span>
-        </div>
-      </li>
-    </ul>
-  </div>
-  <div id="navrow2" class="tabs2">
-    <ul class="tablist">
-      <li><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
-      <li><a href="classes.html"><span>Data&#160;Structure&#160;Index</span></a></li>
-      <li class="current"><a href="functions.html"><span>Data&#160;Fields</span></a></li>
-    </ul>
-  </div>
-  <div id="navrow3" class="tabs2">
-    <ul class="tablist">
-      <li class="current"><a href="functions.html"><span>All</span></a></li>
-      <li><a href="functions_vars.html"><span>Variables</span></a></li>
-    </ul>
-  </div>
-</div><!-- top -->
-<!-- window showing the filter options -->
-<div id="MSearchSelectWindow"
-     onmouseover="return searchBox.OnSearchSelectShow()"
-     onmouseout="return searchBox.OnSearchSelectHide()"
-     onkeydown="return searchBox.OnSearchSelectKey(event)">
-<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Data Structures</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Groups</a></div>
-
-<!-- iframe showing the search results (closed by default) -->
-<div id="MSearchResultsWindow">
-<iframe src="javascript:void(0)" frameborder="0" 
-        name="MSearchResults" id="MSearchResults">
-</iframe>
-</div>
-
-<div class="contents">
-<div class="textblock">Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:</div><ul>
-<li>customFilter
-: <a class="el" href="structtjtransform.html#a43ee1bcdd2a8d7249a756774f78793c1">tjtransform</a>
-</li>
-<li>data
-: <a class="el" href="structtjtransform.html#a688fe8f1a8ecc12a538d9e561cf338e3">tjtransform</a>
-</li>
-<li>denom
-: <a class="el" href="structtjscalingfactor.html#aefbcdf3e9e62274b2d312c695f133ce3">tjscalingfactor</a>
-</li>
-<li>h
-: <a class="el" href="structtjregion.html#aecefc45a26f4d8b60dd4d825c1710115">tjregion</a>
-</li>
-<li>num
-: <a class="el" href="structtjscalingfactor.html#a9b011e57f981ee23083e2c1aa5e640ec">tjscalingfactor</a>
-</li>
-<li>op
-: <a class="el" href="structtjtransform.html#a2525aab4ba6978a1c273f74fef50e498">tjtransform</a>
-</li>
-<li>options
-: <a class="el" href="structtjtransform.html#ac0e74655baa4402209a21e1ae481c8f6">tjtransform</a>
-</li>
-<li>r
-: <a class="el" href="structtjtransform.html#ac324e5e442abec8a961e5bf219db12cf">tjtransform</a>
-</li>
-<li>w
-: <a class="el" href="structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42">tjregion</a>
-</li>
-<li>x
-: <a class="el" href="structtjregion.html#a4b6a37a93997091b26a75831fa291ad9">tjregion</a>
-</li>
-<li>y
-: <a class="el" href="structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2">tjregion</a>
-</li>
-</ul>
-</div><!-- contents -->
-<!-- start footer part -->
-<hr class="footer"/><address class="footer"><small>
-Generated by &#160;<a href="http://www.doxygen.org/index.html">
-<img class="footer" src="doxygen.png" alt="doxygen"/>
-</a> 1.8.3.1
-</small></address>
-</body>
-</html>
diff --git a/src/third_party/libjpeg-turbo/doc/html/functions_vars.html b/src/third_party/libjpeg-turbo/doc/html/functions_vars.html
deleted file mode 100644
index e0a7157..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/functions_vars.html
+++ /dev/null
@@ -1,134 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<meta http-equiv="X-UA-Compatible" content="IE=9"/>
-<meta name="generator" content="Doxygen 1.8.3.1"/>
-<title>TurboJPEG: Data Fields - Variables</title>
-<link href="tabs.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="jquery.js"></script>
-<script type="text/javascript" src="dynsections.js"></script>
-<link href="search/search.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="search/search.js"></script>
-<script type="text/javascript">
-  $(document).ready(function() { searchBox.OnSelectItem(0); });
-</script>
-<link href="doxygen.css" rel="stylesheet" type="text/css" />
-<link href="doxygen-extra.css" rel="stylesheet" type="text/css"/>
-</head>
-<body>
-<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
-<div id="titlearea">
-<table cellspacing="0" cellpadding="0">
- <tbody>
- <tr style="height: 56px;">
-  <td style="padding-left: 0.5em;">
-   <div id="projectname">TurboJPEG
-   &#160;<span id="projectnumber">2.0</span>
-   </div>
-  </td>
- </tr>
- </tbody>
-</table>
-</div>
-<!-- end header part -->
-<!-- Generated by Doxygen 1.8.3.1 -->
-<script type="text/javascript">
-var searchBox = new SearchBox("searchBox", "search",false,'Search');
-</script>
-  <div id="navrow1" class="tabs">
-    <ul class="tablist">
-      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
-      <li><a href="modules.html"><span>Modules</span></a></li>
-      <li class="current"><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
-      <li>
-        <div id="MSearchBox" class="MSearchBoxInactive">
-        <span class="left">
-          <img id="MSearchSelect" src="search/mag_sel.png"
-               onmouseover="return searchBox.OnSearchSelectShow()"
-               onmouseout="return searchBox.OnSearchSelectHide()"
-               alt=""/>
-          <input type="text" id="MSearchField" value="Search" accesskey="S"
-               onfocus="searchBox.OnSearchFieldFocus(true)" 
-               onblur="searchBox.OnSearchFieldFocus(false)" 
-               onkeyup="searchBox.OnSearchFieldChange(event)"/>
-          </span><span class="right">
-            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
-          </span>
-        </div>
-      </li>
-    </ul>
-  </div>
-  <div id="navrow2" class="tabs2">
-    <ul class="tablist">
-      <li><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
-      <li><a href="classes.html"><span>Data&#160;Structure&#160;Index</span></a></li>
-      <li class="current"><a href="functions.html"><span>Data&#160;Fields</span></a></li>
-    </ul>
-  </div>
-  <div id="navrow3" class="tabs2">
-    <ul class="tablist">
-      <li><a href="functions.html"><span>All</span></a></li>
-      <li class="current"><a href="functions_vars.html"><span>Variables</span></a></li>
-    </ul>
-  </div>
-</div><!-- top -->
-<!-- window showing the filter options -->
-<div id="MSearchSelectWindow"
-     onmouseover="return searchBox.OnSearchSelectShow()"
-     onmouseout="return searchBox.OnSearchSelectHide()"
-     onkeydown="return searchBox.OnSearchSelectKey(event)">
-<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Data Structures</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Groups</a></div>
-
-<!-- iframe showing the search results (closed by default) -->
-<div id="MSearchResultsWindow">
-<iframe src="javascript:void(0)" frameborder="0" 
-        name="MSearchResults" id="MSearchResults">
-</iframe>
-</div>
-
-<div class="contents">
-&#160;<ul>
-<li>customFilter
-: <a class="el" href="structtjtransform.html#a43ee1bcdd2a8d7249a756774f78793c1">tjtransform</a>
-</li>
-<li>data
-: <a class="el" href="structtjtransform.html#a688fe8f1a8ecc12a538d9e561cf338e3">tjtransform</a>
-</li>
-<li>denom
-: <a class="el" href="structtjscalingfactor.html#aefbcdf3e9e62274b2d312c695f133ce3">tjscalingfactor</a>
-</li>
-<li>h
-: <a class="el" href="structtjregion.html#aecefc45a26f4d8b60dd4d825c1710115">tjregion</a>
-</li>
-<li>num
-: <a class="el" href="structtjscalingfactor.html#a9b011e57f981ee23083e2c1aa5e640ec">tjscalingfactor</a>
-</li>
-<li>op
-: <a class="el" href="structtjtransform.html#a2525aab4ba6978a1c273f74fef50e498">tjtransform</a>
-</li>
-<li>options
-: <a class="el" href="structtjtransform.html#ac0e74655baa4402209a21e1ae481c8f6">tjtransform</a>
-</li>
-<li>r
-: <a class="el" href="structtjtransform.html#ac324e5e442abec8a961e5bf219db12cf">tjtransform</a>
-</li>
-<li>w
-: <a class="el" href="structtjregion.html#ab6eb73ceef584fc23c8c8097926dce42">tjregion</a>
-</li>
-<li>x
-: <a class="el" href="structtjregion.html#a4b6a37a93997091b26a75831fa291ad9">tjregion</a>
-</li>
-<li>y
-: <a class="el" href="structtjregion.html#a7b3e0c24cfe87acc80e334cafdcf22c2">tjregion</a>
-</li>
-</ul>
-</div><!-- contents -->
-<!-- start footer part -->
-<hr class="footer"/><address class="footer"><small>
-Generated by &#160;<a href="http://www.doxygen.org/index.html">
-<img class="footer" src="doxygen.png" alt="doxygen"/>
-</a> 1.8.3.1
-</small></address>
-</body>
-</html>
diff --git a/src/third_party/libjpeg-turbo/doc/html/group___turbo_j_p_e_g.html b/src/third_party/libjpeg-turbo/doc/html/group___turbo_j_p_e_g.html
deleted file mode 100644
index cef856a..0000000
--- a/src/third_party/libjpeg-turbo/doc/html/group___turbo_j_p_e_g.html
+++ /dev/null
@@ -1,2775 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<meta http-equiv="X-UA-Compatible" content="IE=9"/>
-<meta name="generator" content="Doxygen 1.8.3.1"/>
-<title>TurboJPEG: TurboJPEG</title>
-<link href="tabs.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="jquery.js"></script>
-<script type="text/javascript" src="dynsections.js"></script>
-<link href="search/search.css" rel="stylesheet" type="text/css"/>
-<script type="text/javascript" src="search/search.js"></script>
-<script type="text/javascript">
-  $(document).ready(function() { searchBox.OnSelectItem(0); });
-</script>
-<link href="doxygen.css" rel="stylesheet" type="text/css" />
-<link href="doxygen-extra.css" rel="stylesheet" type="text/css"/>
-</head>
-<body>
-<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
-<div id="titlearea">
-<table cellspacing="0" cellpadding="0">
- <tbody>
- <tr style="height: 56px;">
-  <td style="padding-left: 0.5em;">
-   <div id="projectname">TurboJPEG
-   &#160;<span id="projectnumber">2.0</span>
-   </div>
-  </td>
- </tr>
- </tbody>
-</table>
-</div>
-<!-- end header part -->
-<!-- Generated by Doxygen 1.8.3.1 -->
-<script type="text/javascript">
-var searchBox = new SearchBox("searchBox", "search",false,'Search');
-</script>
-  <div id="navrow1" class="tabs">
-    <ul class="tablist">
-      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
-      <li><a href="modules.html"><span>Modules</span></a></li>
-      <li><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
-      <li>
-        <div id="MSearchBox" class="MSearchBoxInactive">
-        <span class="left">
-          <img id="MSearchSelect" src="search/mag_sel.png"
-               onmouseover="return searchBox.OnSearchSelectShow()"
-               onmouseout="return searchBox.OnSearchSelectHide()"
-               alt=""/>
-          <input type="text" id="MSearchField" value="Search" accesskey="S"
-               onfocus="searchBox.OnSearchFieldFocus(true)" 
-               onblur="searchBox.OnSearchFieldFocus(false)" 
-               onkeyup="searchBox.OnSearchFieldChange(event)"/>
-          </span><span class="right">
-            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
-          </span>
-        </div>
-      </li>
-    </ul>
-  </div>
-</div><!-- top -->
-<!-- window showing the filter options -->
-<div id="MSearchSelectWindow"
-     onmouseover="return searchBox.OnSearchSelectShow()"
-     onmouseout="return searchBox.OnSearchSelectHide()"
-     onkeydown="return searchBox.OnSearchSelectKey(event)">
-<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Data Structures</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Groups</a></div>
-
-<!-- iframe showing the search results (closed by default) -->
-<div id="MSearchResultsWindow">
-<iframe src="javascript:void(0)" frameborder="0" 
-        name="MSearchResults" id="MSearchResults">
-</iframe>
-</div>
-
-<div class="header">
-  <div class="summary">
-<a href="#nested-classes">Data Structures</a> &#124;
-<a href="#define-members">Macros</a> &#124;
-<a href="#typedef-members">Typedefs</a> &#124;
-<a href="#enum-members">Enumerations</a> &#124;
-<a href="#func-members">Functions</a> &#124;
-<a href="#var-members">Variables</a>  </div>
-  <div class="headertitle">
-<div class="title">TurboJPEG</div>  </div>
-</div><!--header-->
-<div class="contents">
-
-<p>TurboJPEG API.  
-<a href="#details">More...</a></p>
-<table class="memberdecls">
-<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="nested-classes"></a>
-Data Structures</h2></td></tr>
-<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="structtjscalingfactor.html">tjscalingfactor</a></td></tr>
-<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Scaling factor.  <a href="structtjscalingfactor.html#details">More...</a><br/></td></tr>
-<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="structtjregion.html">tjregion</a></td></tr>
-<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Cropping region.  <a href="structtjregion.html#details">More...</a><br/></td></tr>
-<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="structtjtransform.html">tjtransform</a></td></tr>
-<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Lossless transform.  <a href="structtjtransform.html#details">More...</a><br/></td></tr>
-<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
-</table><table class="memberdecls">
-<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
-Macros</h2></td></tr>
-<tr class="memitem:ga5ef3d169162ce77ce348e292a0b7477c"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga5ef3d169162ce77ce348e292a0b7477c">TJ_NUMSAMP</a></td></tr>
-<tr class="memdesc:ga5ef3d169162ce77ce348e292a0b7477c"><td class="mdescLeft">&#160;</td><td class="mdescRight">The number of chrominance subsampling options.  <a href="#ga5ef3d169162ce77ce348e292a0b7477c">More...</a><br/></td></tr>
-<tr class="separator:ga5ef3d169162ce77ce348e292a0b7477c"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga7010a4402f54a45ba822ad8675a4655e"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga7010a4402f54a45ba822ad8675a4655e">TJ_NUMPF</a></td></tr>
-<tr class="memdesc:ga7010a4402f54a45ba822ad8675a4655e"><td class="mdescLeft">&#160;</td><td class="mdescRight">The number of pixel formats.  <a href="#ga7010a4402f54a45ba822ad8675a4655e">More...</a><br/></td></tr>
-<tr class="separator:ga7010a4402f54a45ba822ad8675a4655e"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga39f57a6fb02d9cf32e7b6890099b5a71"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga39f57a6fb02d9cf32e7b6890099b5a71">TJ_NUMCS</a></td></tr>
-<tr class="memdesc:ga39f57a6fb02d9cf32e7b6890099b5a71"><td class="mdescLeft">&#160;</td><td class="mdescRight">The number of JPEG colorspaces.  <a href="#ga39f57a6fb02d9cf32e7b6890099b5a71">More...</a><br/></td></tr>
-<tr class="separator:ga39f57a6fb02d9cf32e7b6890099b5a71"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga72ecf4ebe6eb702d3c6f5ca27455e1ec"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga72ecf4ebe6eb702d3c6f5ca27455e1ec">TJFLAG_BOTTOMUP</a></td></tr>
-<tr class="memdesc:ga72ecf4ebe6eb702d3c6f5ca27455e1ec"><td class="mdescLeft">&#160;</td><td class="mdescRight">The uncompressed source/destination image is stored in bottom-up (Windows, OpenGL) order, not top-down (X11) order.  <a href="#ga72ecf4ebe6eb702d3c6f5ca27455e1ec">More...</a><br/></td></tr>
-<tr class="separator:ga72ecf4ebe6eb702d3c6f5ca27455e1ec"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga4ee4506c81177a06f77e2504a22efd2d"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga4ee4506c81177a06f77e2504a22efd2d">TJFLAG_FASTUPSAMPLE</a></td></tr>
-<tr class="memdesc:ga4ee4506c81177a06f77e2504a22efd2d"><td class="mdescLeft">&#160;</td><td class="mdescRight">When decompressing an image that was compressed using chrominance subsampling, use the fastest chrominance upsampling algorithm available in the underlying codec.  <a href="#ga4ee4506c81177a06f77e2504a22efd2d">More...</a><br/></td></tr>
-<tr class="separator:ga4ee4506c81177a06f77e2504a22efd2d"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga8808d403c68b62aaa58a4c1e58e98963"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga8808d403c68b62aaa58a4c1e58e98963">TJFLAG_NOREALLOC</a></td></tr>
-<tr class="memdesc:ga8808d403c68b62aaa58a4c1e58e98963"><td class="mdescLeft">&#160;</td><td class="mdescRight">Disable buffer (re)allocation.  <a href="#ga8808d403c68b62aaa58a4c1e58e98963">More...</a><br/></td></tr>
-<tr class="separator:ga8808d403c68b62aaa58a4c1e58e98963"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gaabce235db80d3f698b27f36cbd453da2"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gaabce235db80d3f698b27f36cbd453da2">TJFLAG_FASTDCT</a></td></tr>
-<tr class="memdesc:gaabce235db80d3f698b27f36cbd453da2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Use the fastest DCT/IDCT algorithm available in the underlying codec.  <a href="#gaabce235db80d3f698b27f36cbd453da2">More...</a><br/></td></tr>
-<tr class="separator:gaabce235db80d3f698b27f36cbd453da2"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gacb233cfd722d66d1ccbf48a7de81f0e0"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gacb233cfd722d66d1ccbf48a7de81f0e0">TJFLAG_ACCURATEDCT</a></td></tr>
-<tr class="memdesc:gacb233cfd722d66d1ccbf48a7de81f0e0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Use the most accurate DCT/IDCT algorithm available in the underlying codec.  <a href="#gacb233cfd722d66d1ccbf48a7de81f0e0">More...</a><br/></td></tr>
-<tr class="separator:gacb233cfd722d66d1ccbf48a7de81f0e0"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga519cfa4ef6c18d9e5b455fdf59306a3a"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga519cfa4ef6c18d9e5b455fdf59306a3a">TJFLAG_STOPONWARNING</a></td></tr>
-<tr class="memdesc:ga519cfa4ef6c18d9e5b455fdf59306a3a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Immediately discontinue the current compression/decompression/transform operation if the underlying codec throws a warning (non-fatal error).  <a href="#ga519cfa4ef6c18d9e5b455fdf59306a3a">More...</a><br/></td></tr>
-<tr class="separator:ga519cfa4ef6c18d9e5b455fdf59306a3a"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga43b426750b46190a25d34a67ef76df1b"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga43b426750b46190a25d34a67ef76df1b">TJFLAG_PROGRESSIVE</a></td></tr>
-<tr class="memdesc:ga43b426750b46190a25d34a67ef76df1b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Use progressive entropy coding in JPEG images generated by the compression and transform functions.  <a href="#ga43b426750b46190a25d34a67ef76df1b">More...</a><br/></td></tr>
-<tr class="separator:ga43b426750b46190a25d34a67ef76df1b"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga79bde1b4a3e2351e00887e47781b966e"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga79bde1b4a3e2351e00887e47781b966e">TJ_NUMERR</a></td></tr>
-<tr class="memdesc:ga79bde1b4a3e2351e00887e47781b966e"><td class="mdescLeft">&#160;</td><td class="mdescRight">The number of error codes.  <a href="#ga79bde1b4a3e2351e00887e47781b966e">More...</a><br/></td></tr>
-<tr class="separator:ga79bde1b4a3e2351e00887e47781b966e"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga0f6dbd18adf38b7d46ac547f0f4d562c"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga0f6dbd18adf38b7d46ac547f0f4d562c">TJ_NUMXOP</a></td></tr>
-<tr class="memdesc:ga0f6dbd18adf38b7d46ac547f0f4d562c"><td class="mdescLeft">&#160;</td><td class="mdescRight">The number of transform operations.  <a href="#ga0f6dbd18adf38b7d46ac547f0f4d562c">More...</a><br/></td></tr>
-<tr class="separator:ga0f6dbd18adf38b7d46ac547f0f4d562c"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga50e03cb5ed115330e212417429600b00"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00">TJXOPT_PERFECT</a></td></tr>
-<tr class="memdesc:ga50e03cb5ed115330e212417429600b00"><td class="mdescLeft">&#160;</td><td class="mdescRight">This option will cause <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> to return an error if the transform is not perfect.  <a href="#ga50e03cb5ed115330e212417429600b00">More...</a><br/></td></tr>
-<tr class="separator:ga50e03cb5ed115330e212417429600b00"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga319826b7eb1583c0595bbe7b95428709"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga319826b7eb1583c0595bbe7b95428709">TJXOPT_TRIM</a></td></tr>
-<tr class="memdesc:ga319826b7eb1583c0595bbe7b95428709"><td class="mdescLeft">&#160;</td><td class="mdescRight">This option will cause <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> to discard any partial MCU blocks that cannot be transformed.  <a href="#ga319826b7eb1583c0595bbe7b95428709">More...</a><br/></td></tr>
-<tr class="separator:ga319826b7eb1583c0595bbe7b95428709"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga9c771a757fc1294add611906b89ab2d2"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga9c771a757fc1294add611906b89ab2d2">TJXOPT_CROP</a></td></tr>
-<tr class="memdesc:ga9c771a757fc1294add611906b89ab2d2"><td class="mdescLeft">&#160;</td><td class="mdescRight">This option will enable lossless cropping.  <a href="#ga9c771a757fc1294add611906b89ab2d2">More...</a><br/></td></tr>
-<tr class="separator:ga9c771a757fc1294add611906b89ab2d2"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga3acee7b48ade1b99e5588736007c2589"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga3acee7b48ade1b99e5588736007c2589">TJXOPT_GRAY</a></td></tr>
-<tr class="memdesc:ga3acee7b48ade1b99e5588736007c2589"><td class="mdescLeft">&#160;</td><td class="mdescRight">This option will discard the color data in the input image and produce a grayscale output image.  <a href="#ga3acee7b48ade1b99e5588736007c2589">More...</a><br/></td></tr>
-<tr class="separator:ga3acee7b48ade1b99e5588736007c2589"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gafbf992bbf6e006705886333703ffab31"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gafbf992bbf6e006705886333703ffab31">TJXOPT_NOOUTPUT</a></td></tr>
-<tr class="memdesc:gafbf992bbf6e006705886333703ffab31"><td class="mdescLeft">&#160;</td><td class="mdescRight">This option will prevent <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> from outputting a JPEG image for this particular transform (this can be used in conjunction with a custom filter to capture the transformed DCT coefficients without transcoding them.)  <a href="#gafbf992bbf6e006705886333703ffab31">More...</a><br/></td></tr>
-<tr class="separator:gafbf992bbf6e006705886333703ffab31"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gad2371c80674584ecc1a7d75e564cf026"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gad2371c80674584ecc1a7d75e564cf026">TJXOPT_PROGRESSIVE</a></td></tr>
-<tr class="memdesc:gad2371c80674584ecc1a7d75e564cf026"><td class="mdescLeft">&#160;</td><td class="mdescRight">This option will enable progressive entropy coding in the output image generated by this particular transform.  <a href="#gad2371c80674584ecc1a7d75e564cf026">More...</a><br/></td></tr>
-<tr class="separator:gad2371c80674584ecc1a7d75e564cf026"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga153b468cfb905d0de61706c838986fe8"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga153b468cfb905d0de61706c838986fe8">TJXOPT_COPYNONE</a></td></tr>
-<tr class="memdesc:ga153b468cfb905d0de61706c838986fe8"><td class="mdescLeft">&#160;</td><td class="mdescRight">This option will prevent <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> from copying any extra markers (including EXIF and ICC profile data) from the source image to the output image.  <a href="#ga153b468cfb905d0de61706c838986fe8">More...</a><br/></td></tr>
-<tr class="separator:ga153b468cfb905d0de61706c838986fe8"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga0aba955473315e405295d978f0c16511"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga0aba955473315e405295d978f0c16511">TJPAD</a>(width)</td></tr>
-<tr class="memdesc:ga0aba955473315e405295d978f0c16511"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pad the given width to the nearest 32-bit boundary.  <a href="#ga0aba955473315e405295d978f0c16511">More...</a><br/></td></tr>
-<tr class="separator:ga0aba955473315e405295d978f0c16511"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga84878bb65404204743aa18cac02781df"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga84878bb65404204743aa18cac02781df">TJSCALED</a>(dimension, scalingFactor)</td></tr>
-<tr class="memdesc:ga84878bb65404204743aa18cac02781df"><td class="mdescLeft">&#160;</td><td class="mdescRight">Compute the scaled value of <code>dimension</code> using the given scaling factor.  <a href="#ga84878bb65404204743aa18cac02781df">More...</a><br/></td></tr>
-<tr class="separator:ga84878bb65404204743aa18cac02781df"><td class="memSeparator" colspan="2">&#160;</td></tr>
-</table><table class="memberdecls">
-<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
-Typedefs</h2></td></tr>
-<tr class="memitem:gaa29f3189c41be12ec5dee7caec318a31"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="structtjtransform.html">tjtransform</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gaa29f3189c41be12ec5dee7caec318a31">tjtransform</a></td></tr>
-<tr class="memdesc:gaa29f3189c41be12ec5dee7caec318a31"><td class="mdescLeft">&#160;</td><td class="mdescRight">Lossless transform.  <a href="#gaa29f3189c41be12ec5dee7caec318a31">More...</a><br/></td></tr>
-<tr class="separator:gaa29f3189c41be12ec5dee7caec318a31"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga758d2634ecb4949de7815cba621f5763"><td class="memItemLeft" align="right" valign="top">typedef void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a></td></tr>
-<tr class="memdesc:ga758d2634ecb4949de7815cba621f5763"><td class="mdescLeft">&#160;</td><td class="mdescRight">TurboJPEG instance handle.  <a href="#ga758d2634ecb4949de7815cba621f5763">More...</a><br/></td></tr>
-<tr class="separator:ga758d2634ecb4949de7815cba621f5763"><td class="memSeparator" colspan="2">&#160;</td></tr>
-</table><table class="memberdecls">
-<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="enum-members"></a>
-Enumerations</h2></td></tr>
-<tr class="memitem:ga1d047060ea80bb9820d540bb928e9074"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074">TJSAMP</a> { <br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3">TJSAMP_444</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404">TJSAMP_422</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737">TJSAMP_420</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248">TJSAMP_GRAY</a>, 
-<br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974">TJSAMP_440</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2">TJSAMP_411</a>
-<br/>
- }</td></tr>
-<tr class="memdesc:ga1d047060ea80bb9820d540bb928e9074"><td class="mdescLeft">&#160;</td><td class="mdescRight">Chrominance subsampling options.  <a href="group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074">More...</a><br/></td></tr>
-<tr class="separator:ga1d047060ea80bb9820d540bb928e9074"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gac916144e26c3817ac514e64ae5d12e2a"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a">TJPF</a> { <br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c">TJPF_RGB</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839">TJPF_BGR</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01">TJPF_RGBX</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8">TJPF_BGRX</a>, 
-<br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af">TJPF_XBGR</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84">TJPF_XRGB</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a">TJPF_GRAY</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12">TJPF_RGBA</a>, 
-<br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4">TJPF_BGRA</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081">TJPF_ABGR</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c">TJPF_ARGB</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b">TJPF_CMYK</a>, 
-<br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed">TJPF_UNKNOWN</a>
-<br/>
- }</td></tr>
-<tr class="memdesc:gac916144e26c3817ac514e64ae5d12e2a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pixel formats.  <a href="group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a">More...</a><br/></td></tr>
-<tr class="separator:gac916144e26c3817ac514e64ae5d12e2a"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga4f83ad3368e0e29d1957be0efa7c3720"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720">TJCS</a> { <br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a677cb7ccb85c4038ac41964a2e09e555">TJCS_RGB</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a7389b8f65bb387ffedce3efd0d78ec75">TJCS_YCbCr</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720ab3e7d6a87f695e45b81c1b5262b5a50a">TJCS_GRAY</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a6c8b636152ac8195b869587db315ee53">TJCS_CMYK</a>, 
-<br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a53839e0fe867b76b58d16b0a1a7c598e">TJCS_YCCK</a>
-<br/>
- }</td></tr>
-<tr class="memdesc:ga4f83ad3368e0e29d1957be0efa7c3720"><td class="mdescLeft">&#160;</td><td class="mdescRight">JPEG colorspaces.  <a href="group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720">More...</a><br/></td></tr>
-<tr class="separator:ga4f83ad3368e0e29d1957be0efa7c3720"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gafbc17cfa57d0d5d11fea35ac025950fe"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gafbc17cfa57d0d5d11fea35ac025950fe">TJERR</a> { <a class="el" href="group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950fea342dd6e2aedb47bb257b4e7568329b59">TJERR_WARNING</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#ggafbc17cfa57d0d5d11fea35ac025950feafc9cceeada13122b09e4851e3788039a">TJERR_FATAL</a>
- }</td></tr>
-<tr class="memdesc:gafbc17cfa57d0d5d11fea35ac025950fe"><td class="mdescLeft">&#160;</td><td class="mdescRight">Error codes.  <a href="group___turbo_j_p_e_g.html#gafbc17cfa57d0d5d11fea35ac025950fe">More...</a><br/></td></tr>
-<tr class="separator:gafbc17cfa57d0d5d11fea35ac025950fe"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga2de531af4e7e6c4f124908376b354866"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866">TJXOP</a> { <br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27">TJXOP_NONE</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce">TJXOP_HFLIP</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d">TJXOP_VFLIP</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d">TJXOP_TRANSPOSE</a>, 
-<br/>
-&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4">TJXOP_TRANSVERSE</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128">TJXOP_ROT90</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692">TJXOP_ROT180</a>, 
-<a class="el" href="group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08">TJXOP_ROT270</a>
-<br/>
- }</td></tr>
-<tr class="memdesc:ga2de531af4e7e6c4f124908376b354866"><td class="mdescLeft">&#160;</td><td class="mdescRight">Transform operations for <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a>  <a href="group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866">More...</a><br/></td></tr>
-<tr class="separator:ga2de531af4e7e6c4f124908376b354866"><td class="memSeparator" colspan="2">&#160;</td></tr>
-</table><table class="memberdecls">
-<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
-Functions</h2></td></tr>
-<tr class="memitem:ga9d63a05fc6d813f4aae06107041a37e8"><td class="memItemLeft" align="right" valign="top">DLLEXPORT <a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga9d63a05fc6d813f4aae06107041a37e8">tjInitCompress</a> (void)</td></tr>
-<tr class="memdesc:ga9d63a05fc6d813f4aae06107041a37e8"><td class="mdescLeft">&#160;</td><td class="mdescRight">Create a TurboJPEG compressor instance.  <a href="#ga9d63a05fc6d813f4aae06107041a37e8">More...</a><br/></td></tr>
-<tr class="separator:ga9d63a05fc6d813f4aae06107041a37e8"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gafbdce0112fd78fd38efae841443a9bcf"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gafbdce0112fd78fd38efae841443a9bcf">tjCompress2</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *srcBuf, int width, int pitch, int height, int pixelFormat, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)</td></tr>
-<tr class="memdesc:gafbdce0112fd78fd38efae841443a9bcf"><td class="mdescLeft">&#160;</td><td class="mdescRight">Compress an RGB, grayscale, or CMYK image into a JPEG image.  <a href="#gafbdce0112fd78fd38efae841443a9bcf">More...</a><br/></td></tr>
-<tr class="separator:gafbdce0112fd78fd38efae841443a9bcf"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga7622a459b79aa1007e005b58783f875b"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga7622a459b79aa1007e005b58783f875b">tjCompressFromYUV</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *srcBuf, int width, int pad, int height, int subsamp, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)</td></tr>
-<tr class="memdesc:ga7622a459b79aa1007e005b58783f875b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Compress a YUV planar image into a JPEG image.  <a href="#ga7622a459b79aa1007e005b58783f875b">More...</a><br/></td></tr>
-<tr class="separator:ga7622a459b79aa1007e005b58783f875b"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga29ec5dfbd2d84b8724e951d6fa0d5d9e"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga29ec5dfbd2d84b8724e951d6fa0d5d9e">tjCompressFromYUVPlanes</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char **srcPlanes, int width, const int *strides, int height, int subsamp, unsigned char **jpegBuf, unsigned long *jpegSize, int jpegQual, int flags)</td></tr>
-<tr class="memdesc:ga29ec5dfbd2d84b8724e951d6fa0d5d9e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Compress a set of Y, U (Cb), and V (Cr) image planes into a JPEG image.  <a href="#ga29ec5dfbd2d84b8724e951d6fa0d5d9e">More...</a><br/></td></tr>
-<tr class="separator:ga29ec5dfbd2d84b8724e951d6fa0d5d9e"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga67ac12fee79073242cb216e07c9f1f90"><td class="memItemLeft" align="right" valign="top">DLLEXPORT unsigned long&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga67ac12fee79073242cb216e07c9f1f90">tjBufSize</a> (int width, int height, int jpegSubsamp)</td></tr>
-<tr class="memdesc:ga67ac12fee79073242cb216e07c9f1f90"><td class="mdescLeft">&#160;</td><td class="mdescRight">The maximum size of the buffer (in bytes) required to hold a JPEG image with the given parameters.  <a href="#ga67ac12fee79073242cb216e07c9f1f90">More...</a><br/></td></tr>
-<tr class="separator:ga67ac12fee79073242cb216e07c9f1f90"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga2be2b9969d4df9ecce9b05deed273194"><td class="memItemLeft" align="right" valign="top">DLLEXPORT unsigned long&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga2be2b9969d4df9ecce9b05deed273194">tjBufSizeYUV2</a> (int width, int pad, int height, int subsamp)</td></tr>
-<tr class="memdesc:ga2be2b9969d4df9ecce9b05deed273194"><td class="mdescLeft">&#160;</td><td class="mdescRight">The size of the buffer (in bytes) required to hold a YUV planar image with the given parameters.  <a href="#ga2be2b9969d4df9ecce9b05deed273194">More...</a><br/></td></tr>
-<tr class="separator:ga2be2b9969d4df9ecce9b05deed273194"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gab4ab7b24f6e797d79abaaa670373961d"><td class="memItemLeft" align="right" valign="top">DLLEXPORT unsigned long&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gab4ab7b24f6e797d79abaaa670373961d">tjPlaneSizeYUV</a> (int componentID, int width, int stride, int height, int subsamp)</td></tr>
-<tr class="memdesc:gab4ab7b24f6e797d79abaaa670373961d"><td class="mdescLeft">&#160;</td><td class="mdescRight">The size of the buffer (in bytes) required to hold a YUV image plane with the given parameters.  <a href="#gab4ab7b24f6e797d79abaaa670373961d">More...</a><br/></td></tr>
-<tr class="separator:gab4ab7b24f6e797d79abaaa670373961d"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga63fb66bb1e36c74008c4634360becbb1"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga63fb66bb1e36c74008c4634360becbb1">tjPlaneWidth</a> (int componentID, int width, int subsamp)</td></tr>
-<tr class="memdesc:ga63fb66bb1e36c74008c4634360becbb1"><td class="mdescLeft">&#160;</td><td class="mdescRight">The plane width of a YUV image plane with the given parameters.  <a href="#ga63fb66bb1e36c74008c4634360becbb1">More...</a><br/></td></tr>
-<tr class="separator:ga63fb66bb1e36c74008c4634360becbb1"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga1a209696c6a80748f20e134b3c64789f"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga1a209696c6a80748f20e134b3c64789f">tjPlaneHeight</a> (int componentID, int height, int subsamp)</td></tr>
-<tr class="memdesc:ga1a209696c6a80748f20e134b3c64789f"><td class="mdescLeft">&#160;</td><td class="mdescRight">The plane height of a YUV image plane with the given parameters.  <a href="#ga1a209696c6a80748f20e134b3c64789f">More...</a><br/></td></tr>
-<tr class="separator:ga1a209696c6a80748f20e134b3c64789f"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gac519b922cdf446e97d0cdcba513636bf"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gac519b922cdf446e97d0cdcba513636bf">tjEncodeYUV3</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *srcBuf, int width, int pitch, int height, int pixelFormat, unsigned char *dstBuf, int pad, int subsamp, int flags)</td></tr>
-<tr class="memdesc:gac519b922cdf446e97d0cdcba513636bf"><td class="mdescLeft">&#160;</td><td class="mdescRight">Encode an RGB or grayscale image into a YUV planar image.  <a href="#gac519b922cdf446e97d0cdcba513636bf">More...</a><br/></td></tr>
-<tr class="separator:gac519b922cdf446e97d0cdcba513636bf"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gae2d04c72457fe7f4d60cf78ab1b1feb1"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gae2d04c72457fe7f4d60cf78ab1b1feb1">tjEncodeYUVPlanes</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *srcBuf, int width, int pitch, int height, int pixelFormat, unsigned char **dstPlanes, int *strides, int subsamp, int flags)</td></tr>
-<tr class="memdesc:gae2d04c72457fe7f4d60cf78ab1b1feb1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Encode an RGB or grayscale image into separate Y, U (Cb), and V (Cr) image planes.  <a href="#gae2d04c72457fe7f4d60cf78ab1b1feb1">More...</a><br/></td></tr>
-<tr class="separator:gae2d04c72457fe7f4d60cf78ab1b1feb1"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga52300eac3f3d9ef4bab303bc244f62d3"><td class="memItemLeft" align="right" valign="top">DLLEXPORT <a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga52300eac3f3d9ef4bab303bc244f62d3">tjInitDecompress</a> (void)</td></tr>
-<tr class="memdesc:ga52300eac3f3d9ef4bab303bc244f62d3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Create a TurboJPEG decompressor instance.  <a href="#ga52300eac3f3d9ef4bab303bc244f62d3">More...</a><br/></td></tr>
-<tr class="separator:ga52300eac3f3d9ef4bab303bc244f62d3"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga0595681096bba7199cc6f3533cb25f77"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga0595681096bba7199cc6f3533cb25f77">tjDecompressHeader3</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height, int *jpegSubsamp, int *jpegColorspace)</td></tr>
-<tr class="memdesc:ga0595681096bba7199cc6f3533cb25f77"><td class="mdescLeft">&#160;</td><td class="mdescRight">Retrieve information about a JPEG image without decompressing it.  <a href="#ga0595681096bba7199cc6f3533cb25f77">More...</a><br/></td></tr>
-<tr class="separator:ga0595681096bba7199cc6f3533cb25f77"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gac3854476006b10787bd128f7ede48057"><td class="memItemLeft" align="right" valign="top">DLLEXPORT <a class="el" href="structtjscalingfactor.html">tjscalingfactor</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gac3854476006b10787bd128f7ede48057">tjGetScalingFactors</a> (int *numscalingfactors)</td></tr>
-<tr class="memdesc:gac3854476006b10787bd128f7ede48057"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a list of fractional scaling factors that the JPEG decompressor in this implementation of TurboJPEG supports.  <a href="#gac3854476006b10787bd128f7ede48057">More...</a><br/></td></tr>
-<tr class="separator:gac3854476006b10787bd128f7ede48057"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gae9eccef8b682a48f43a9117c231ed013"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gae9eccef8b682a48f43a9117c231ed013">tjDecompress2</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat, int flags)</td></tr>
-<tr class="memdesc:gae9eccef8b682a48f43a9117c231ed013"><td class="mdescLeft">&#160;</td><td class="mdescRight">Decompress a JPEG image to an RGB, grayscale, or CMYK image.  <a href="#gae9eccef8b682a48f43a9117c231ed013">More...</a><br/></td></tr>
-<tr class="separator:gae9eccef8b682a48f43a9117c231ed013"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga04d1e839ff9a0860dd1475cff78d3364"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga04d1e839ff9a0860dd1475cff78d3364">tjDecompressToYUV2</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char *dstBuf, int width, int pad, int height, int flags)</td></tr>
-<tr class="memdesc:ga04d1e839ff9a0860dd1475cff78d3364"><td class="mdescLeft">&#160;</td><td class="mdescRight">Decompress a JPEG image to a YUV planar image.  <a href="#ga04d1e839ff9a0860dd1475cff78d3364">More...</a><br/></td></tr>
-<tr class="separator:ga04d1e839ff9a0860dd1475cff78d3364"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gaa59f901a5258ada5bd0185ad59368540"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gaa59f901a5258ada5bd0185ad59368540">tjDecompressToYUVPlanes</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *jpegBuf, unsigned long jpegSize, unsigned char **dstPlanes, int width, int *strides, int height, int flags)</td></tr>
-<tr class="memdesc:gaa59f901a5258ada5bd0185ad59368540"><td class="mdescLeft">&#160;</td><td class="mdescRight">Decompress a JPEG image into separate Y, U (Cb), and V (Cr) image planes.  <a href="#gaa59f901a5258ada5bd0185ad59368540">More...</a><br/></td></tr>
-<tr class="separator:gaa59f901a5258ada5bd0185ad59368540"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga70abbf38f77a26fd6da8813bef96f695"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga70abbf38f77a26fd6da8813bef96f695">tjDecodeYUV</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *srcBuf, int pad, int subsamp, unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat, int flags)</td></tr>
-<tr class="memdesc:ga70abbf38f77a26fd6da8813bef96f695"><td class="mdescLeft">&#160;</td><td class="mdescRight">Decode a YUV planar image into an RGB or grayscale image.  <a href="#ga70abbf38f77a26fd6da8813bef96f695">More...</a><br/></td></tr>
-<tr class="separator:ga70abbf38f77a26fd6da8813bef96f695"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga10e837c07fa9d25770565b237d3898d9"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga10e837c07fa9d25770565b237d3898d9">tjDecodeYUVPlanes</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char **srcPlanes, const int *strides, int subsamp, unsigned char *dstBuf, int width, int pitch, int height, int pixelFormat, int flags)</td></tr>
-<tr class="memdesc:ga10e837c07fa9d25770565b237d3898d9"><td class="mdescLeft">&#160;</td><td class="mdescRight">Decode a set of Y, U (Cb), and V (Cr) image planes into an RGB or grayscale image.  <a href="#ga10e837c07fa9d25770565b237d3898d9">More...</a><br/></td></tr>
-<tr class="separator:ga10e837c07fa9d25770565b237d3898d9"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga928beff6ac248ceadf01089fc6b41957"><td class="memItemLeft" align="right" valign="top">DLLEXPORT <a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga928beff6ac248ceadf01089fc6b41957">tjInitTransform</a> (void)</td></tr>
-<tr class="memdesc:ga928beff6ac248ceadf01089fc6b41957"><td class="mdescLeft">&#160;</td><td class="mdescRight">Create a new TurboJPEG transformer instance.  <a href="#ga928beff6ac248ceadf01089fc6b41957">More...</a><br/></td></tr>
-<tr class="separator:ga928beff6ac248ceadf01089fc6b41957"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga9cb8abf4cc91881e04a0329b2270be25"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25">tjTransform</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle, const unsigned char *jpegBuf, unsigned long jpegSize, int n, unsigned char **dstBufs, unsigned long *dstSizes, <a class="el" href="structtjtransform.html">tjtransform</a> *transforms, int flags)</td></tr>
-<tr class="memdesc:ga9cb8abf4cc91881e04a0329b2270be25"><td class="mdescLeft">&#160;</td><td class="mdescRight">Losslessly transform a JPEG image into another JPEG image.  <a href="#ga9cb8abf4cc91881e04a0329b2270be25">More...</a><br/></td></tr>
-<tr class="separator:ga9cb8abf4cc91881e04a0329b2270be25"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga75f355fa27225ba1a4ee392c852394d2"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga75f355fa27225ba1a4ee392c852394d2">tjDestroy</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle)</td></tr>
-<tr class="memdesc:ga75f355fa27225ba1a4ee392c852394d2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroy a TurboJPEG compressor, decompressor, or transformer instance.  <a href="#ga75f355fa27225ba1a4ee392c852394d2">More...</a><br/></td></tr>
-<tr class="separator:ga75f355fa27225ba1a4ee392c852394d2"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gaec627dd4c5f30b7a775a7aea3bec5d83"><td class="memItemLeft" align="right" valign="top">DLLEXPORT unsigned char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gaec627dd4c5f30b7a775a7aea3bec5d83">tjAlloc</a> (int bytes)</td></tr>
-<tr class="memdesc:gaec627dd4c5f30b7a775a7aea3bec5d83"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocate an image buffer for use with TurboJPEG.  <a href="#gaec627dd4c5f30b7a775a7aea3bec5d83">More...</a><br/></td></tr>
-<tr class="separator:gaec627dd4c5f30b7a775a7aea3bec5d83"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gaffbd83c375e79f5db4b5c5d8ad4466e7"><td class="memItemLeft" align="right" valign="top">DLLEXPORT unsigned char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7">tjLoadImage</a> (const char *filename, int *width, int align, int *height, int *pixelFormat, int flags)</td></tr>
-<tr class="memdesc:gaffbd83c375e79f5db4b5c5d8ad4466e7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Load an uncompressed image from disk into memory.  <a href="#gaffbd83c375e79f5db4b5c5d8ad4466e7">More...</a><br/></td></tr>
-<tr class="separator:gaffbd83c375e79f5db4b5c5d8ad4466e7"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga6f445b22d8933ae4815b3370a538d879"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga6f445b22d8933ae4815b3370a538d879">tjSaveImage</a> (const char *filename, unsigned char *buffer, int width, int pitch, int height, int pixelFormat, int flags)</td></tr>
-<tr class="memdesc:ga6f445b22d8933ae4815b3370a538d879"><td class="mdescLeft">&#160;</td><td class="mdescRight">Save an uncompressed image from memory to disk.  <a href="#ga6f445b22d8933ae4815b3370a538d879">More...</a><br/></td></tr>
-<tr class="separator:ga6f445b22d8933ae4815b3370a538d879"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gaea863d2da0cdb609563aabdf9196514b"><td class="memItemLeft" align="right" valign="top">DLLEXPORT void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b">tjFree</a> (unsigned char *buffer)</td></tr>
-<tr class="memdesc:gaea863d2da0cdb609563aabdf9196514b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Free an image buffer previously allocated by TurboJPEG.  <a href="#gaea863d2da0cdb609563aabdf9196514b">More...</a><br/></td></tr>
-<tr class="separator:gaea863d2da0cdb609563aabdf9196514b"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga1ead8574f9f39fbafc6b497124e7aafa"><td class="memItemLeft" align="right" valign="top">DLLEXPORT char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga1ead8574f9f39fbafc6b497124e7aafa">tjGetErrorStr2</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle)</td></tr>
-<tr class="memdesc:ga1ead8574f9f39fbafc6b497124e7aafa"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a descriptive error message explaining why the last command failed.  <a href="#ga1ead8574f9f39fbafc6b497124e7aafa">More...</a><br/></td></tr>
-<tr class="separator:ga1ead8574f9f39fbafc6b497124e7aafa"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga414feeffbf860ebd31c745df203de410"><td class="memItemLeft" align="right" valign="top">DLLEXPORT int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga414feeffbf860ebd31c745df203de410">tjGetErrorCode</a> (<a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a> handle)</td></tr>
-<tr class="memdesc:ga414feeffbf860ebd31c745df203de410"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns a code indicating the severity of the last error.  <a href="#ga414feeffbf860ebd31c745df203de410">More...</a><br/></td></tr>
-<tr class="separator:ga414feeffbf860ebd31c745df203de410"><td class="memSeparator" colspan="2">&#160;</td></tr>
-</table><table class="memberdecls">
-<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="var-members"></a>
-Variables</h2></td></tr>
-<tr class="memitem:ga9e61e7cd47a15a173283ba94e781308c"><td class="memItemLeft" align="right" valign="top">static const int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c">tjMCUWidth</a> [<a class="el" href="group___turbo_j_p_e_g.html#ga5ef3d169162ce77ce348e292a0b7477c">TJ_NUMSAMP</a>]</td></tr>
-<tr class="memdesc:ga9e61e7cd47a15a173283ba94e781308c"><td class="mdescLeft">&#160;</td><td class="mdescRight">MCU block width (in pixels) for a given level of chrominance subsampling.  <a href="#ga9e61e7cd47a15a173283ba94e781308c">More...</a><br/></td></tr>
-<tr class="separator:ga9e61e7cd47a15a173283ba94e781308c"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gabd247bb9fecb393eca57366feb8327bf"><td class="memItemLeft" align="right" valign="top">static const int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf">tjMCUHeight</a> [<a class="el" href="group___turbo_j_p_e_g.html#ga5ef3d169162ce77ce348e292a0b7477c">TJ_NUMSAMP</a>]</td></tr>
-<tr class="memdesc:gabd247bb9fecb393eca57366feb8327bf"><td class="mdescLeft">&#160;</td><td class="mdescRight">MCU block height (in pixels) for a given level of chrominance subsampling.  <a href="#gabd247bb9fecb393eca57366feb8327bf">More...</a><br/></td></tr>
-<tr class="separator:gabd247bb9fecb393eca57366feb8327bf"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gadd9b446742ac8a3923f7992c7988fea8"><td class="memItemLeft" align="right" valign="top">static const int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8">tjRedOffset</a> [<a class="el" href="group___turbo_j_p_e_g.html#ga7010a4402f54a45ba822ad8675a4655e">TJ_NUMPF</a>]</td></tr>
-<tr class="memdesc:gadd9b446742ac8a3923f7992c7988fea8"><td class="mdescLeft">&#160;</td><td class="mdescRight">Red offset (in bytes) for a given pixel format.  <a href="#gadd9b446742ac8a3923f7992c7988fea8">More...</a><br/></td></tr>
-<tr class="separator:gadd9b446742ac8a3923f7992c7988fea8"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga82d6e35da441112a411da41923c0ba2f"><td class="memItemLeft" align="right" valign="top">static const int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga82d6e35da441112a411da41923c0ba2f">tjGreenOffset</a> [<a class="el" href="group___turbo_j_p_e_g.html#ga7010a4402f54a45ba822ad8675a4655e">TJ_NUMPF</a>]</td></tr>
-<tr class="memdesc:ga82d6e35da441112a411da41923c0ba2f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Green offset (in bytes) for a given pixel format.  <a href="#ga82d6e35da441112a411da41923c0ba2f">More...</a><br/></td></tr>
-<tr class="separator:ga82d6e35da441112a411da41923c0ba2f"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga84e2e35d3f08025f976ec1ec53693dea"><td class="memItemLeft" align="right" valign="top">static const int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga84e2e35d3f08025f976ec1ec53693dea">tjBlueOffset</a> [<a class="el" href="group___turbo_j_p_e_g.html#ga7010a4402f54a45ba822ad8675a4655e">TJ_NUMPF</a>]</td></tr>
-<tr class="memdesc:ga84e2e35d3f08025f976ec1ec53693dea"><td class="mdescLeft">&#160;</td><td class="mdescRight">Blue offset (in bytes) for a given pixel format.  <a href="#ga84e2e35d3f08025f976ec1ec53693dea">More...</a><br/></td></tr>
-<tr class="separator:ga84e2e35d3f08025f976ec1ec53693dea"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:ga5af0ab065feefd526debf1e20c43e837"><td class="memItemLeft" align="right" valign="top">static const int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#ga5af0ab065feefd526debf1e20c43e837">tjAlphaOffset</a> [<a class="el" href="group___turbo_j_p_e_g.html#ga7010a4402f54a45ba822ad8675a4655e">TJ_NUMPF</a>]</td></tr>
-<tr class="memdesc:ga5af0ab065feefd526debf1e20c43e837"><td class="mdescLeft">&#160;</td><td class="mdescRight">Alpha offset (in bytes) for a given pixel format.  <a href="#ga5af0ab065feefd526debf1e20c43e837">More...</a><br/></td></tr>
-<tr class="separator:ga5af0ab065feefd526debf1e20c43e837"><td class="memSeparator" colspan="2">&#160;</td></tr>
-<tr class="memitem:gad77cf8fe5b2bfd3cb3f53098146abb4c"><td class="memItemLeft" align="right" valign="top">static const int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group___turbo_j_p_e_g.html#gad77cf8fe5b2bfd3cb3f53098146abb4c">tjPixelSize</a> [<a class="el" href="group___turbo_j_p_e_g.html#ga7010a4402f54a45ba822ad8675a4655e">TJ_NUMPF</a>]</td></tr>
-<tr class="memdesc:gad77cf8fe5b2bfd3cb3f53098146abb4c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pixel size (in bytes) for a given pixel format.  <a href="#gad77cf8fe5b2bfd3cb3f53098146abb4c">More...</a><br/></td></tr>
-<tr class="separator:gad77cf8fe5b2bfd3cb3f53098146abb4c"><td class="memSeparator" colspan="2">&#160;</td></tr>
-</table>
-<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
-<p>TurboJPEG API. </p>
-<p>This API provides an interface for generating, decoding, and transforming planar YUV and JPEG images in memory.</p>
-<p><a class="anchor" id="YUVnotes"></a></p>
-<h2>YUV Image Format Notes</h2>
-<p>Technically, the JPEG format uses the YCbCr colorspace (which is technically not a colorspace but a color transform), but per the convention of the digital video community, the TurboJPEG API uses "YUV" to refer to an image format consisting of Y, Cb, and Cr image planes.</p>
-<p>Each plane is simply a 2D array of bytes, each byte representing the value of one of the components (Y, Cb, or Cr) at a particular location in the image. The width and height of each plane are determined by the image width, height, and level of chrominance subsampling. The luminance plane width is the image width padded to the nearest multiple of the horizontal subsampling factor (2 in the case of 4:2:0 and 4:2:2, 4 in the case of 4:1:1, 1 in the case of 4:4:4 or grayscale.) Similarly, the luminance plane height is the image height padded to the nearest multiple of the vertical subsampling factor (2 in the case of 4:2:0 or 4:4:0, 1 in the case of 4:4:4 or grayscale.) This is irrespective of any additional padding that may be specified as an argument to the various YUV functions. The chrominance plane width is equal to the luminance plane width divided by the horizontal subsampling factor, and the chrominance plane height is equal to the luminance plane height divided by the vertical subsampling factor.</p>
-<p>For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is used, then the luminance plane would be 36 x 35 bytes, and each of the chrominance planes would be 18 x 35 bytes. If you specify a line padding of 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, and each of the chrominance planes would be 20 x 35 bytes. </p>
-<h2 class="groupheader">Macro Definition Documentation</h2>
-<a class="anchor" id="ga39f57a6fb02d9cf32e7b6890099b5a71"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJ_NUMCS</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>The number of JPEG colorspaces. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga79bde1b4a3e2351e00887e47781b966e"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJ_NUMERR</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>The number of error codes. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga7010a4402f54a45ba822ad8675a4655e"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJ_NUMPF</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>The number of pixel formats. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga5ef3d169162ce77ce348e292a0b7477c"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJ_NUMSAMP</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>The number of chrominance subsampling options. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga0f6dbd18adf38b7d46ac547f0f4d562c"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJ_NUMXOP</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>The number of transform operations. </p>
-
-</div>
-</div>
-<a class="anchor" id="gacb233cfd722d66d1ccbf48a7de81f0e0"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJFLAG_ACCURATEDCT</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Use the most accurate DCT/IDCT algorithm available in the underlying codec. </p>
-<p>The default if this flag is not specified is implementation-specific. For example, the implementation of TurboJPEG for libjpeg[-turbo] uses the fast algorithm by default when compressing, because this has been shown to have only a very slight effect on accuracy, but it uses the accurate algorithm when decompressing, because this has been shown to have a larger effect. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga72ecf4ebe6eb702d3c6f5ca27455e1ec"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJFLAG_BOTTOMUP</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>The uncompressed source/destination image is stored in bottom-up (Windows, OpenGL) order, not top-down (X11) order. </p>
-
-</div>
-</div>
-<a class="anchor" id="gaabce235db80d3f698b27f36cbd453da2"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJFLAG_FASTDCT</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Use the fastest DCT/IDCT algorithm available in the underlying codec. </p>
-<p>The default if this flag is not specified is implementation-specific. For example, the implementation of TurboJPEG for libjpeg[-turbo] uses the fast algorithm by default when compressing, because this has been shown to have only a very slight effect on accuracy, but it uses the accurate algorithm when decompressing, because this has been shown to have a larger effect. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga4ee4506c81177a06f77e2504a22efd2d"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJFLAG_FASTUPSAMPLE</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>When decompressing an image that was compressed using chrominance subsampling, use the fastest chrominance upsampling algorithm available in the underlying codec. </p>
-<p>The default is to use smooth upsampling, which creates a smooth transition between neighboring chrominance components in order to reduce upsampling artifacts in the decompressed image. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga8808d403c68b62aaa58a4c1e58e98963"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJFLAG_NOREALLOC</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Disable buffer (re)allocation. </p>
-<p>If passed to one of the JPEG compression or transform functions, this flag will cause those functions to generate an error if the JPEG image buffer is invalid or too small rather than attempting to allocate or reallocate that buffer. This reproduces the behavior of earlier versions of TurboJPEG. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga43b426750b46190a25d34a67ef76df1b"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJFLAG_PROGRESSIVE</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Use progressive entropy coding in JPEG images generated by the compression and transform functions. </p>
-<p>Progressive entropy coding will generally improve compression relative to baseline entropy coding (the default), but it will reduce compression and decompression performance considerably. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga519cfa4ef6c18d9e5b455fdf59306a3a"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJFLAG_STOPONWARNING</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Immediately discontinue the current compression/decompression/transform operation if the underlying codec throws a warning (non-fatal error). </p>
-<p>The default behavior is to allow the operation to complete unless a fatal error is encountered. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga0aba955473315e405295d978f0c16511"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJPAD</td>
-          <td>(</td>
-          <td class="paramtype">&#160;</td>
-          <td class="paramname">width</td><td>)</td>
-          <td></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Pad the given width to the nearest 32-bit boundary. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga84878bb65404204743aa18cac02781df"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJSCALED</td>
-          <td>(</td>
-          <td class="paramtype">&#160;</td>
-          <td class="paramname">dimension, </td>
-        </tr>
-        <tr>
-          <td class="paramkey"></td>
-          <td></td>
-          <td class="paramtype">&#160;</td>
-          <td class="paramname">scalingFactor&#160;</td>
-        </tr>
-        <tr>
-          <td></td>
-          <td>)</td>
-          <td></td><td></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Compute the scaled value of <code>dimension</code> using the given scaling factor. </p>
-<p>This macro performs the integer equivalent of <code>ceil(dimension * scalingFactor)</code>. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga153b468cfb905d0de61706c838986fe8"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJXOPT_COPYNONE</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>This option will prevent <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> from copying any extra markers (including EXIF and ICC profile data) from the source image to the output image. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga9c771a757fc1294add611906b89ab2d2"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJXOPT_CROP</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>This option will enable lossless cropping. </p>
-<p>See <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> for more information. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga3acee7b48ade1b99e5588736007c2589"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJXOPT_GRAY</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>This option will discard the color data in the input image and produce a grayscale output image. </p>
-
-</div>
-</div>
-<a class="anchor" id="gafbf992bbf6e006705886333703ffab31"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJXOPT_NOOUTPUT</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>This option will prevent <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> from outputting a JPEG image for this particular transform (this can be used in conjunction with a custom filter to capture the transformed DCT coefficients without transcoding them.) </p>
-
-</div>
-</div>
-<a class="anchor" id="ga50e03cb5ed115330e212417429600b00"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJXOPT_PERFECT</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>This option will cause <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> to return an error if the transform is not perfect. </p>
-<p>Lossless transforms operate on MCU blocks, whose size depends on the level of chrominance subsampling used (see <a class="el" href="group___turbo_j_p_e_g.html#ga9e61e7cd47a15a173283ba94e781308c" title="MCU block width (in pixels) for a given level of chrominance subsampling.">tjMCUWidth</a> and <a class="el" href="group___turbo_j_p_e_g.html#gabd247bb9fecb393eca57366feb8327bf" title="MCU block height (in pixels) for a given level of chrominance subsampling.">tjMCUHeight</a>.) If the image's width or height is not evenly divisible by the MCU block size, then there will be partial MCU blocks on the right and/or bottom edges. It is not possible to move these partial MCU blocks to the top or left of the image, so any transform that would require that is "imperfect." If this option is not specified, then any partial MCU blocks that cannot be transformed will be left in place, which will create odd-looking strips on the right or bottom edge of the image. </p>
-
-</div>
-</div>
-<a class="anchor" id="gad2371c80674584ecc1a7d75e564cf026"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJXOPT_PROGRESSIVE</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>This option will enable progressive entropy coding in the output image generated by this particular transform. </p>
-<p>Progressive entropy coding will generally improve compression relative to baseline entropy coding (the default), but it will reduce compression and decompression performance considerably. </p>
-
-</div>
-</div>
-<a class="anchor" id="ga319826b7eb1583c0595bbe7b95428709"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">#define TJXOPT_TRIM</td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>This option will cause <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> to discard any partial MCU blocks that cannot be transformed. </p>
-
-</div>
-</div>
-<h2 class="groupheader">Typedef Documentation</h2>
-<a class="anchor" id="ga758d2634ecb4949de7815cba621f5763"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">typedef void* <a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>TurboJPEG instance handle. </p>
-
-</div>
-</div>
-<a class="anchor" id="gaa29f3189c41be12ec5dee7caec318a31"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">typedef struct <a class="el" href="structtjtransform.html">tjtransform</a>  <a class="el" href="structtjtransform.html">tjtransform</a></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Lossless transform. </p>
-
-</div>
-</div>
-<h2 class="groupheader">Enumeration Type Documentation</h2>
-<a class="anchor" id="ga4f83ad3368e0e29d1957be0efa7c3720"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">enum <a class="el" href="group___turbo_j_p_e_g.html#ga4f83ad3368e0e29d1957be0efa7c3720">TJCS</a></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>JPEG colorspaces. </p>
-<table class="fieldtable">
-<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><em><a class="anchor" id="gga4f83ad3368e0e29d1957be0efa7c3720a677cb7ccb85c4038ac41964a2e09e555"></a>TJCS_RGB</em>&nbsp;</td><td class="fielddoc">
-<p>RGB colorspace. </p>
-<p>When compressing the JPEG image, the R, G, and B components in the source image are reordered into image planes, but no colorspace conversion or subsampling is performed. RGB JPEG images can be decompressed to any of the extended RGB pixel formats or grayscale, but they cannot be decompressed to YUV images. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga4f83ad3368e0e29d1957be0efa7c3720a7389b8f65bb387ffedce3efd0d78ec75"></a>TJCS_YCbCr</em>&nbsp;</td><td class="fielddoc">
-<p>YCbCr colorspace. </p>
-<p>YCbCr is not an absolute colorspace but rather a mathematical transformation of RGB designed solely for storage and transmission. YCbCr images must be converted to RGB before they can actually be displayed. In the YCbCr colorspace, the Y (luminance) component represents the black &amp; white portion of the original image, and the Cb and Cr (chrominance) components represent the color portion of the original image. Originally, the analog equivalent of this transformation allowed the same signal to drive both black &amp; white and color televisions, but JPEG images use YCbCr primarily because it allows the color data to be optionally subsampled for the purposes of reducing bandwidth or disk space. YCbCr is the most common JPEG colorspace, and YCbCr JPEG images can be compressed from and decompressed to any of the extended RGB pixel formats or grayscale, or they can be decompressed to YUV planar images. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga4f83ad3368e0e29d1957be0efa7c3720ab3e7d6a87f695e45b81c1b5262b5a50a"></a>TJCS_GRAY</em>&nbsp;</td><td class="fielddoc">
-<p>Grayscale colorspace. </p>
-<p>The JPEG image retains only the luminance data (Y component), and any color data from the source image is discarded. Grayscale JPEG images can be compressed from and decompressed to any of the extended RGB pixel formats or grayscale, or they can be decompressed to YUV planar images. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga4f83ad3368e0e29d1957be0efa7c3720a6c8b636152ac8195b869587db315ee53"></a>TJCS_CMYK</em>&nbsp;</td><td class="fielddoc">
-<p>CMYK colorspace. </p>
-<p>When compressing the JPEG image, the C, M, Y, and K components in the source image are reordered into image planes, but no colorspace conversion or subsampling is performed. CMYK JPEG images can only be decompressed to CMYK pixels. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga4f83ad3368e0e29d1957be0efa7c3720a53839e0fe867b76b58d16b0a1a7c598e"></a>TJCS_YCCK</em>&nbsp;</td><td class="fielddoc">
-<p>YCCK colorspace. </p>
-<p>YCCK (AKA "YCbCrK") is not an absolute colorspace but rather a mathematical transformation of CMYK designed solely for storage and transmission. It is to CMYK as YCbCr is to RGB. CMYK pixels can be reversibly transformed into YCCK, and as with YCbCr, the chrominance components in the YCCK pixels can be subsampled without incurring major perceptual loss. YCCK JPEG images can only be compressed from and decompressed to CMYK pixels. </p>
-</td></tr>
-</table>
-
-</div>
-</div>
-<a class="anchor" id="gafbc17cfa57d0d5d11fea35ac025950fe"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">enum <a class="el" href="group___turbo_j_p_e_g.html#gafbc17cfa57d0d5d11fea35ac025950fe">TJERR</a></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Error codes. </p>
-<table class="fieldtable">
-<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><em><a class="anchor" id="ggafbc17cfa57d0d5d11fea35ac025950fea342dd6e2aedb47bb257b4e7568329b59"></a>TJERR_WARNING</em>&nbsp;</td><td class="fielddoc">
-<p>The error was non-fatal and recoverable, but the image may still be corrupt. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggafbc17cfa57d0d5d11fea35ac025950feafc9cceeada13122b09e4851e3788039a"></a>TJERR_FATAL</em>&nbsp;</td><td class="fielddoc">
-<p>The error was fatal and non-recoverable. </p>
-</td></tr>
-</table>
-
-</div>
-</div>
-<a class="anchor" id="gac916144e26c3817ac514e64ae5d12e2a"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">enum <a class="el" href="group___turbo_j_p_e_g.html#gac916144e26c3817ac514e64ae5d12e2a">TJPF</a></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Pixel formats. </p>
-<table class="fieldtable">
-<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aa7ce93230bff449518ce387c17e6ed37c"></a>TJPF_RGB</em>&nbsp;</td><td class="fielddoc">
-<p>RGB pixel format. </p>
-<p>The red, green, and blue components in the image are stored in 3-byte pixels in the order R, G, B from lowest to highest byte address within each pixel. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aab10624437fb8ef495a0b153e65749839"></a>TJPF_BGR</em>&nbsp;</td><td class="fielddoc">
-<p>BGR pixel format. </p>
-<p>The red, green, and blue components in the image are stored in 3-byte pixels in the order B, G, R from lowest to highest byte address within each pixel. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01"></a>TJPF_RGBX</em>&nbsp;</td><td class="fielddoc">
-<p>RGBX pixel format. </p>
-<p>The red, green, and blue components in the image are stored in 4-byte pixels in the order R, G, B from lowest to highest byte address within each pixel. The X component is ignored when compressing and undefined when decompressing. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8"></a>TJPF_BGRX</em>&nbsp;</td><td class="fielddoc">
-<p>BGRX pixel format. </p>
-<p>The red, green, and blue components in the image are stored in 4-byte pixels in the order B, G, R from lowest to highest byte address within each pixel. The X component is ignored when compressing and undefined when decompressing. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af"></a>TJPF_XBGR</em>&nbsp;</td><td class="fielddoc">
-<p>XBGR pixel format. </p>
-<p>The red, green, and blue components in the image are stored in 4-byte pixels in the order R, G, B from highest to lowest byte address within each pixel. The X component is ignored when compressing and undefined when decompressing. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84"></a>TJPF_XRGB</em>&nbsp;</td><td class="fielddoc">
-<p>XRGB pixel format. </p>
-<p>The red, green, and blue components in the image are stored in 4-byte pixels in the order B, G, R from highest to lowest byte address within each pixel. The X component is ignored when compressing and undefined when decompressing. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aa5431b54b015337705f13118073711a1a"></a>TJPF_GRAY</em>&nbsp;</td><td class="fielddoc">
-<p>Grayscale pixel format. </p>
-<p>Each 1-byte pixel represents a luminance (brightness) level from 0 to 255. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aa88d2e88fab67f6503cf972e14851cc12"></a>TJPF_RGBA</em>&nbsp;</td><td class="fielddoc">
-<p>RGBA pixel format. </p>
-<p>This is the same as <a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01">TJPF_RGBX</a>, except that when decompressing, the X component is guaranteed to be 0xFF, which can be interpreted as an opaque alpha channel. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aac037ff1845cf9b74bb81a3659c2b9fb4"></a>TJPF_BGRA</em>&nbsp;</td><td class="fielddoc">
-<p>BGRA pixel format. </p>
-<p>This is the same as <a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa2a1fbf569ca79897eae886e3376ca4c8">TJPF_BGRX</a>, except that when decompressing, the X component is guaranteed to be 0xFF, which can be interpreted as an opaque alpha channel. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aa1ba1a7f1631dbeaa49a0a85fc4a40081"></a>TJPF_ABGR</em>&nbsp;</td><td class="fielddoc">
-<p>ABGR pixel format. </p>
-<p>This is the same as <a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af">TJPF_XBGR</a>, except that when decompressing, the X component is guaranteed to be 0xFF, which can be interpreted as an opaque alpha channel. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aae8f846ed9d9de99b6e1dfe448848765c"></a>TJPF_ARGB</em>&nbsp;</td><td class="fielddoc">
-<p>ARGB pixel format. </p>
-<p>This is the same as <a class="el" href="group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84">TJPF_XRGB</a>, except that when decompressing, the X component is guaranteed to be 0xFF, which can be interpreted as an opaque alpha channel. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aa7f5100ec44c91994e243f1cf55553f8b"></a>TJPF_CMYK</em>&nbsp;</td><td class="fielddoc">
-<p>CMYK pixel format. </p>
-<p>Unlike RGB, which is an additive color model used primarily for display, CMYK (Cyan/Magenta/Yellow/Key) is a subtractive color model used primarily for printing. In the CMYK color model, the value of each color component typically corresponds to an amount of cyan, magenta, yellow, or black ink that is applied to a white background. In order to convert between CMYK and RGB, it is necessary to use a color management system (CMS.) A CMS will attempt to map colors within the printer's gamut to perceptually similar colors in the display's gamut and vice versa, but the mapping is typically not 1:1 or reversible, nor can it be defined with a simple formula. Thus, such a conversion is out of scope for a codec library. However, the TurboJPEG API allows for compressing CMYK pixels into a YCCK JPEG image (see <a class="el" href="group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a53839e0fe867b76b58d16b0a1a7c598e" title="YCCK colorspace.">TJCS_YCCK</a>) and decompressing YCCK JPEG images into CMYK pixels. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="ggac916144e26c3817ac514e64ae5d12e2aa84c1a6cead7952998e2fb895844a21ed"></a>TJPF_UNKNOWN</em>&nbsp;</td><td class="fielddoc">
-<p>Unknown pixel format. </p>
-<p>Currently this is only used by <a class="el" href="group___turbo_j_p_e_g.html#gaffbd83c375e79f5db4b5c5d8ad4466e7" title="Load an uncompressed image from disk into memory.">tjLoadImage()</a>. </p>
-</td></tr>
-</table>
-
-</div>
-</div>
-<a class="anchor" id="ga1d047060ea80bb9820d540bb928e9074"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">enum <a class="el" href="group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074">TJSAMP</a></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Chrominance subsampling options. </p>
-<p>When pixels are converted from RGB to YCbCr (see <a class="el" href="group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a7389b8f65bb387ffedce3efd0d78ec75" title="YCbCr colorspace.">TJCS_YCbCr</a>) or from CMYK to YCCK (see <a class="el" href="group___turbo_j_p_e_g.html#gga4f83ad3368e0e29d1957be0efa7c3720a53839e0fe867b76b58d16b0a1a7c598e" title="YCCK colorspace.">TJCS_YCCK</a>) as part of the JPEG compression process, some of the Cb and Cr (chrominance) components can be discarded or averaged together to produce a smaller image with little perceptible loss of image clarity (the human eye is more sensitive to small changes in brightness than to small changes in color.) This is called "chrominance subsampling". </p>
-<table class="fieldtable">
-<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><em><a class="anchor" id="gga1d047060ea80bb9820d540bb928e9074afb8da4f44197837bdec0a4f593dacae3"></a>TJSAMP_444</em>&nbsp;</td><td class="fielddoc">
-<p>4:4:4 chrominance subsampling (no chrominance subsampling). </p>
-<p>The JPEG or YUV image will contain one chrominance component for every pixel in the source image. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404"></a>TJSAMP_422</em>&nbsp;</td><td class="fielddoc">
-<p>4:2:2 chrominance subsampling. </p>
-<p>The JPEG or YUV image will contain one chrominance component for every 2x1 block of pixels in the source image. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737"></a>TJSAMP_420</em>&nbsp;</td><td class="fielddoc">
-<p>4:2:0 chrominance subsampling. </p>
-<p>The JPEG or YUV image will contain one chrominance component for every 2x2 block of pixels in the source image. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248"></a>TJSAMP_GRAY</em>&nbsp;</td><td class="fielddoc">
-<p>Grayscale. </p>
-<p>The JPEG or YUV image will contain no chrominance components. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974"></a>TJSAMP_440</em>&nbsp;</td><td class="fielddoc">
-<p>4:4:0 chrominance subsampling. </p>
-<p>The JPEG or YUV image will contain one chrominance component for every 1x2 block of pixels in the source image.</p>
-<dl class="section note"><dt>Note</dt><dd>4:4:0 subsampling is not fully accelerated in libjpeg-turbo. </dd></dl>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2"></a>TJSAMP_411</em>&nbsp;</td><td class="fielddoc">
-<p>4:1:1 chrominance subsampling. </p>
-<p>The JPEG or YUV image will contain one chrominance component for every 4x1 block of pixels in the source image. JPEG images compressed with 4:1:1 subsampling will be almost exactly the same size as those compressed with 4:2:0 subsampling, and in the aggregate, both subsampling methods produce approximately the same perceptual quality. However, 4:1:1 is better able to reproduce sharp horizontal features.</p>
-<dl class="section note"><dt>Note</dt><dd>4:1:1 subsampling is not fully accelerated in libjpeg-turbo. </dd></dl>
-</td></tr>
-</table>
-
-</div>
-</div>
-<a class="anchor" id="ga2de531af4e7e6c4f124908376b354866"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">enum <a class="el" href="group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866">TJXOP</a></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Transform operations for <a class="el" href="group___turbo_j_p_e_g.html#ga9cb8abf4cc91881e04a0329b2270be25" title="Losslessly transform a JPEG image into another JPEG image.">tjTransform()</a> </p>
-<table class="fieldtable">
-<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><em><a class="anchor" id="gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27"></a>TJXOP_NONE</em>&nbsp;</td><td class="fielddoc">
-<p>Do not transform the position of the image pixels. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce"></a>TJXOP_HFLIP</em>&nbsp;</td><td class="fielddoc">
-<p>Flip (mirror) image horizontally. </p>
-<p>This transform is imperfect if there are any partial MCU blocks on the right edge (see <a class="el" href="group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00" title="This option will cause tjTransform() to return an error if the transform is not perfect.">TJXOPT_PERFECT</a>.) </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga2de531af4e7e6c4f124908376b354866a324eddfbec53b7e691f61e56929d0d5d"></a>TJXOP_VFLIP</em>&nbsp;</td><td class="fielddoc">
-<p>Flip (mirror) image vertically. </p>
-<p>This transform is imperfect if there are any partial MCU blocks on the bottom edge (see <a class="el" href="group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00" title="This option will cause tjTransform() to return an error if the transform is not perfect.">TJXOPT_PERFECT</a>.) </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga2de531af4e7e6c4f124908376b354866a31060aed199f886afdd417f80499c32d"></a>TJXOP_TRANSPOSE</em>&nbsp;</td><td class="fielddoc">
-<p>Transpose image (flip/mirror along upper left to lower right axis.) This transform is always perfect. </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga2de531af4e7e6c4f124908376b354866af3b14d488aea6ece9e5b3df73a74d6a4"></a>TJXOP_TRANSVERSE</em>&nbsp;</td><td class="fielddoc">
-<p>Transverse transpose image (flip/mirror along upper right to lower left axis.) This transform is imperfect if there are any partial MCU blocks in the image (see <a class="el" href="group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00" title="This option will cause tjTransform() to return an error if the transform is not perfect.">TJXOPT_PERFECT</a>.) </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga2de531af4e7e6c4f124908376b354866a43b2bbb23bc4bd548422d43fbe9af128"></a>TJXOP_ROT90</em>&nbsp;</td><td class="fielddoc">
-<p>Rotate image clockwise by 90 degrees. </p>
-<p>This transform is imperfect if there are any partial MCU blocks on the bottom edge (see <a class="el" href="group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00" title="This option will cause tjTransform() to return an error if the transform is not perfect.">TJXOPT_PERFECT</a>.) </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga2de531af4e7e6c4f124908376b354866a140952eb8dd0300accfcc22726d69692"></a>TJXOP_ROT180</em>&nbsp;</td><td class="fielddoc">
-<p>Rotate image 180 degrees. </p>
-<p>This transform is imperfect if there are any partial MCU blocks in the image (see <a class="el" href="group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00" title="This option will cause tjTransform() to return an error if the transform is not perfect.">TJXOPT_PERFECT</a>.) </p>
-</td></tr>
-<tr><td class="fieldname"><em><a class="anchor" id="gga2de531af4e7e6c4f124908376b354866a3064ee5dfb7f032df332818587567a08"></a>TJXOP_ROT270</em>&nbsp;</td><td class="fielddoc">
-<p>Rotate image counter-clockwise by 90 degrees. </p>
-<p>This transform is imperfect if there are any partial MCU blocks on the right edge (see <a class="el" href="group___turbo_j_p_e_g.html#ga50e03cb5ed115330e212417429600b00" title="This option will cause tjTransform() to return an error if the transform is not perfect.">TJXOPT_PERFECT</a>.) </p>
-</td></tr>
-</table>
-
-</div>
-</div>
-<h2 class="groupheader">Function Documentation</h2>
-<a class="anchor" id="gaec627dd4c5f30b7a775a7aea3bec5d83"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">DLLEXPORT unsigned char* tjAlloc </td>
-          <td>(</td>
-          <td class="paramtype">int&#160;</td>
-          <td class="paramname"><em>bytes</em></td><td>)</td>
-          <td></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>Allocate an image buffer for use with TurboJPEG. </p>
-<p>You should always use this function to allocate the JPEG destination buffer(s) for the compression and transform functions unless you are disabling automatic buffer (re)allocation (by setting <a class="el" href="group___turbo_j_p_e_g.html#ga8808d403c68b62aaa58a4c1e58e98963" title="Disable buffer (re)allocation.">TJFLAG_NOREALLOC</a>.)</p>
-<dl class="params"><dt>Parameters</dt><dd>
-  <table class="params">
-    <tr><td class="paramname">bytes</td><td>the number of bytes to allocate</td></tr>
-  </table>
-  </dd>
-</dl>
-<dl class="section return"><dt>Returns</dt><dd>a pointer to a newly-allocated buffer with the specified number of bytes.</dd></dl>
-<dl class="section see"><dt>See Also</dt><dd><a class="el" href="group___turbo_j_p_e_g.html#gaea863d2da0cdb609563aabdf9196514b" title="Free an image buffer previously allocated by TurboJPEG.">tjFree()</a> </dd></dl>
-
-</div>
-</div>
-<a class="anchor" id="ga67ac12fee79073242cb216e07c9f1f90"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">DLLEXPORT unsigned long tjBufSize </td>
-          <td>(</td>
-          <td class="paramtype">int&#160;</td>
-          <td class="paramname"><em>width</em>, </td>
-        </tr>
-        <tr>
-          <td class="paramkey"></td>
-          <td></td>
-          <td class="paramtype">int&#160;</td>
-          <td class="paramname"><em>height</em>, </td>
-        </tr>
-        <tr>
-          <td class="paramkey"></td>
-          <td></td>
-          <td class="paramtype">int&#160;</td>
-          <td class="paramname"><em>jpegSubsamp</em>&#160;</td>
-        </tr>
-        <tr>
-          <td></td>
-          <td>)</td>
-          <td></td><td></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>The maximum size of the buffer (in bytes) required to hold a JPEG image with the given parameters. </p>
-<p>The number of bytes returned by this function is larger than the size of the uncompressed source image. The reason for this is that the JPEG format uses 16-bit coefficients, and it is thus possible for a very high-quality JPEG image with very high-frequency content to expand rather than compress when converted to the JPEG format. Such images represent a very rare corner case, but since there is no way to predict the size of a JPEG image prior to compression, the corner case has to be handled.</p>
-<dl class="params"><dt>Parameters</dt><dd>
-  <table class="params">
-    <tr><td class="paramname">width</td><td>width (in pixels) of the image</td></tr>
-    <tr><td class="paramname">height</td><td>height (in pixels) of the image</td></tr>
-    <tr><td class="paramname">jpegSubsamp</td><td>the level of chrominance subsampling to be used when generating the JPEG image (see <a class="el" href="group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074">Chrominance subsampling options</a>.)</td></tr>
-  </table>
-  </dd>
-</dl>
-<dl class="section return"><dt>Returns</dt><dd>the maximum size of the buffer (in bytes) required to hold the image, or -1 if the arguments are out of bounds. </dd></dl>
-
-</div>
-</div>
-<a class="anchor" id="ga2be2b9969d4df9ecce9b05deed273194"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">DLLEXPORT unsigned long tjBufSizeYUV2 </td>
-          <td>(</td>
-          <td class="paramtype">int&#160;</td>
-          <td class="paramname"><em>width</em>, </td>
-        </tr>
-        <tr>
-          <td class="paramkey"></td>
-          <td></td>
-          <td class="paramtype">int&#160;</td>
-          <td class="paramname"><em>pad</em>, </td>
-        </tr>
-        <tr>
-          <td class="paramkey"></td>
-          <td></td>
-          <td class="paramtype">int&#160;</td>
-          <td class="paramname"><em>height</em>, </td>
-        </tr>
-        <tr>
-          <td class="paramkey"></td>
-          <td></td>
-          <td class="paramtype">int&#160;</td>
-          <td class="paramname"><em>subsamp</em>&#160;</td>
-        </tr>
-        <tr>
-          <td></td>
-          <td>)</td>
-          <td></td><td></td>
-        </tr>
-      </table>
-</div><div class="memdoc">
-
-<p>The size of the buffer (in bytes) required to hold a YUV planar image with the given parameters. </p>
-<dl class="params"><dt>Parameters</dt><dd>
-  <table class="params">
-    <tr><td class="paramname">width</td><td>width (in pixels) of the image</td></tr>
-    <tr><td class="paramname">pad</td><td>the width of each line in each plane of the image is padded to the nearest multiple of this number of bytes (must be a power of 2.)</td></tr>
-    <tr><td class="paramname">height</td><td>height (in pixels) of the image</td></tr>
-    <tr><td class="paramname">subsamp</td><td>level of chrominance subsampling in the image (see <a class="el" href="group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074">Chrominance subsampling options</a>.)</td></tr>
-  </table>
-  </dd>
-</dl>
-<dl class="section return"><dt>Returns</dt><dd>the size of the buffer (in bytes) required to hold the image, or -1 if the arguments are out of bounds. </dd></dl>
-
-</div>
-</div>
-<a class="anchor" id="gafbdce0112fd78fd38efae841443a9bcf"></a>
-<div class="memitem">
-<div class="memproto">
-      <table class="memname">
-        <tr>
-          <td class="memname">DLLEXPORT int tjCompress2 </td>
-          <td>(</td>
-          <td class="paramtype"><a class="el" href="group___turbo_j_p_e_g.html#ga758d2634ecb4949de7815cba621f5763">tjhandle</a>&#160;</td>
-          <td class="paramname"><em>handle</em>, </td>
-        </tr>
-        <tr>
-          <td class=&quo