diff --git a/docs/_data/navigation.yml b/docs/_data/navigation.yml
index 612e2fd37f..de9ea36f99 100644
--- a/docs/_data/navigation.yml
+++ b/docs/_data/navigation.yml
@@ -45,6 +45,8 @@ en:
url: retrieving-metadata.html
- title: Live streaming
url: live-streaming.html
+ - title: Network stacks
+ url: network-stacks.html
- title: Debug logging
url: debug-logging.html
- title: Analytics
diff --git a/docs/network-stacks.md b/docs/network-stacks.md
new file mode 100644
index 0000000000..e0f2197176
--- /dev/null
+++ b/docs/network-stacks.md
@@ -0,0 +1,176 @@
+---
+title: Network stacks
+---
+
+ExoPlayer is commonly used for streaming media over the internet. It supports
+multiple network stacks for making its underlying network requests. Your choice
+of network stack can have a significant impact on streaming performance.
+
+This page outlines how to configure ExoPlayer to use your network stack of
+choice, lists the available options, and provides some guidance on how to choose
+a network stack for your application.
+
+## Configuring ExoPlayer to use a specific network stack ##
+
+ExoPlayer loads data through `DataSource` components, which it obtains from
+`DataSource.Factory` instances that are injected from application code.
+
+If your application only needs to play http(s) content, selecting a network
+stack is as simple as updating any `DataSource.Factory` instances that your
+application injects to be instances of the `HttpDataSource.Factory`
+that corresponds to the network stack you wish to use. If your application also
+needs to play non-http(s) content such as local files, use
+
+~~~
+new DefaultDataSourceFactory(
+ ...
+ /* baseDataSourceFactory= */ new PreferredHttpDataSource.Factory(...));
+~~~
+{: .language-java}
+
+where `PreferredHttpDataSource.Factory` is the factory corresponding to your
+preferred network stack. The `DefaultDataSourceFactory` layer adds in support
+for non-http(s) sources such as local files.
+
+The example below shows how to build a `SimpleExoPlayer` that will use
+the Cronet network stack and also support playback of non-http(s) content.
+
+~~~
+// Given a CronetEngine and Executor, build a CronetDataSource.Factory.
+CronetDataSource.Factory cronetDataSourceFactory =
+ new CronetDataSource.Factory(cronetEngine, executor);
+
+// Wrap the CronetDataSource.Factory in a DefaultDataSourceFactory, which adds
+// in support for requesting data from other sources (e.g., files, resources,
+// etc).
+DefaultDataSourceFactory dataSourceFactory =
+ new DefaultDataSourceFactory(
+ context,
+ /* baseDataSourceFactory= */ cronetDataSourceFactory);
+
+// Inject the DefaultDataSourceFactory when creating the player.
+SimpleExoPlayer player =
+ new SimpleExoPlayer.Builder(context)
+ .setMediaSourceFactory(new DefaultMediaSourceFactory(dataSourceFactory))
+ .build();
+~~~
+{: .language-java}
+
+## Supported network stacks ##
+
+ExoPlayer provides direct support for Cronet, OkHttp and Android's built-in
+network stack. It can also be extended to support any other network stack that
+works on Android.
+
+### Cronet ###
+
+[Cronet](https://developer.android.com/guide/topics/connectivity/cronet) is the
+Chromium network stack made available to Android apps as a library. It takes
+advantage of multiple technologies that reduce the latency and increase the
+throughput of the network requests that your app needs to work, including those
+made by ExoPlayer. It natively supports the HTTP, HTTP/2, and HTTP/3 over QUIC
+protocols. Cronet is used by some of the world's biggest streaming applications,
+including YouTube.
+
+ExoPlayer supports Cronet via its
+[Cronet extension](https://github.com/google/ExoPlayer/tree/dev-v2/extensions/cronet).
+Please see the extension's `README.md` for detailed instructions on how to use
+it. Note that the Cronet extension is able to use three underlying Cronet
+implementations:
+
+1. **Google Play Services:** We recommend using this implementation in most
+ cases, and falling back to Android's built-in network stack
+ (i.e., `DefaultHttpDataSource`) if Google Play Services is not available.
+1. **Cronet Embedded:** May be a good choice if a large percentage of your users
+ are in markets where Google Play Services is not widely available, or if you
+ want to control the exact version of the Cronet implementation being used. The
+ major disadvantage of Cronet Embedded is that it adds approximately 8MB to
+ your application.
+1. **Cronet Fallback:** The fallback implementation of Cronet implements
+ Cronet's API as a wrapper around Android's built-in network stack. It should
+ not be used with ExoPlayer, since using Android's built-in network stack
+ directly (i.e., by using `DefaultHttpDataSource`) is more efficient.
+
+### OkHttp ###
+
+[OkHttp](https://square.github.io/okhttp/) is another modern network stack that
+is widely used by many popular Android applications. It supports HTTP and
+HTTP/2, but does not yet support HTTP/3 over QUIC.
+
+ExoPlayer supports OkHttp via its
+[OkHttp extension](https://github.com/google/ExoPlayer/tree/dev-v2/extensions/okhttp).
+Please see the extension's `README.md` for detailed instructions on how to use
+it. When using the OkHttp extension, the network stack is embedded within the
+application. This is similar to Cronet Embedded, however OkHttp is significantly
+smaller, adding under 1MB to your application.
+
+### Android's built-in network stack ###
+
+ExoPlayer supports use of Android's built-in network stack with
+`DefaultHttpDataSource` and `DefaultHttpDataSource.Factory`, which are part of
+the core ExoPlayer library.
+
+The exact network stack implementation depends on the software running on the
+underlying device. On most devices (as of 2021) only HTTP is supported (i.e.,
+HTTP/2 and HTTP/3 over QUIC are not supported).
+
+### Other network stacks ###
+
+It's possible for applications to integrate other network stacks with ExoPlayer.
+To do this, implement an `HttpDataSource` that wraps the network stack,
+together with a corresponding `HttpDataSource.Factory`. ExoPlayer's Cronet and
+OkHttp extensions are good examples of how to do this.
+
+When integrating with a pure Java network stack, it's a good idea to implement a
+`DataSourceContractTest` to check that your `HttpDataSource` implementation
+behaves correctly. `OkHttpDataSourceContractTest` in the OkHttp extension is a
+good example of how to do this.
+
+## Choosing a network stack ##
+
+The table below outlines the pros and cons of the network stacks supported by
+ExoPlayer.
+
+| Network stack | Protocols | APK size impact | Notes |
+|:---|:--:|:--:|:---|
+| Cronet (Google Play Services) | HTTP
HTTP/2
HTTP/3 over QUIC | Small
(<100KB) | Requires Google Play Services. Cronet version updated automatically |
+| Cronet (Embedded) | HTTP
HTTP/2
HTTP/3 over QUIC | Large
(~8MB) | Cronet version controlled by app developer |
+| Cronet (Fallback) | HTTP
(varies by device) | Small
(<100KB) | Not recommended for ExoPlayer |
+| OkHttp | HTTP
HTTP/2 | Small
(<1MB) | Requires Kotlin runtime |
+| Built-in network stack | HTTP
(varies by device) | None | Implementation varies by device |
+
+The HTTP/2 and HTTP/3 over QUIC protocols can significantly improve media
+streaming performance. In particular when streaming adaptive media distributed
+via a content distribution network (CDN), there are cases for which use of these
+protocols can allow CDNs to operate much more efficiently. For this reason,
+Cronet's support for both HTTP/2 and HTTP/3 over QUIC (and OkHttp's support for
+HTTP/2), is a major benefit compared to using Android's built-in network stack,
+provided the servers on which the content is hosted also support these
+protocols.
+
+When considering media streaming in isolation, we recommend use of Cronet
+provided by Google Play Services, falling back to `DefaultHttpDataSource` if
+Google Play Services is unavailable. This recommendation strikes a good balance
+between enabling use of HTTP/2 and HTTP/3 over QUIC on most devices, and
+avoiding a significant increase in APK size. There are exceptions to this
+recommendation. For cases where Google Play Services is likely to be unavailable
+on a significant fraction of devices that will be running your application,
+using Cronet Embedded or OkHttp may be more appropriate. Use of the built-in
+network stack may be acceptable if APK size is a critical concern, or if media
+streaming is only a minor part of your application's functionality.
+
+Beyond just media, it's normally a good idea to choose a single network stack
+for all of the networking performed by your application. This allows resources
+(e.g., sockets) to be efficiently pooled and shared between ExoPlayer and other
+application components.
+
+To assist with resource sharing, it's recommended to use a single `CronetEngine`
+or `OkHttpClient` instance throughout your application, when using Cronet or
+OkHttp respectively.
+{:.info}
+
+Since your application will most likely need to perform networking not related
+to media playback, your choice of network stack should ultimately factor in our
+recommendations above for media streaming in isolation, the requirements of any
+other components that perform networking, and their relative importance to your
+application.