Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion drm.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ Belos is an example of the usage of the DRM fields in the editor with different
</p>

## Widevine L1
Widevine L1 is supported for Meta Quest device only. If you need to play Widevine L1 content, please refer to [HISPlayer Meta Quest SDK Sample](https://hisplayer.github.io/UnityMetaQuest-SDK/#/setup-guide?id=_21-import-hisplayer-meta-quest-sdk-sample)
Widevine L1 is supported only with **External Surface** render mode.
If other render modes are used, the DRM level is automatically downgraded to L3 internally.

11 changes: 11 additions & 0 deletions hisplayer-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ The following public APIs are provided by **HISPlayerManager**:
* **public RawImage rawImage**: Reference to the Unity Raw Image.
* **public RenderTexture renderTexture**: Reference to the Unity Render Texture.
* **public IntPtr externalSurface**: Reference to the external surface object.
* **public Transform xrLayerTransform**: Reference to the external surface object. Transform that places and sizes this stream's OpenXR video layer — normally the quad you would otherwise have put a renderer on. Its scale is the quad's size in metres and its active state shows or hides the layer; no component has to be added to it. Set this and the SDK owns the whole external-surface path: it creates the swapchain, works out on its own whether the content must be protected for Widevine DRM L1, and wires the resulting Android Surface to the player. Leave empty to supply externalSurface yourself. (Platforms: Android, OpenXR)
* **public int xrLayerOrder**: Reference to the external surface object. Composition order of the XR video layer, relative to the whole Unity scene rather than to individual objects: 1 or higher composites the video over everything the camera renders — including world-space Canvases, whose Order in Layer has no effect here — while -1 or lower puts it behind, so a Canvas shows on top of the video. Going behind needs the camera cleared to a solid colour with alpha 0, which the SDK does for you; the skybox cannot be drawn while a video layer is behind the scene. Never 0: that is the order of Unity's own Default Scene Layer, and setting it here would silently overwrite one with the other. Must be unique across streams too, and a stereo layer takes two orders — this one and the next. (Platforms: Android, OpenXR)
* **public bool xrLayerMatchVideoAspect**: Reference to the external surface object. Shrink the XR video layer's quad to the video's aspect ratio, so a 21:9 film is not stretched to fill a 16:9 quad. The quad never grows past the Transform's scale. Turn this off to always fill it. (Platforms: Android, OpenXR)
* **public HISPlayerXRLayerProjection xrLayerProjection**: Reference to the external surface object. How the XR video layer projects the picture. Quad is a flat screen placed by the Transform above. Equirect360 and Equirect180 wrap it around the viewer for 360/180 footage, where only the Transform's rotation matters. (Platforms: Android, OpenXR)
* **public HISPlayerStereoMode xrLayerStereoMode**: Reference to the external surface object. Frame packing of stereoscopic footage: the left and right eye images live in one video frame, side by side or one above the other, and the layer shows each eye its own half. None for ordinary flat footage. A stereo layer occupies two composition orders — this one and the next one up. (Platforms: Android, OpenXR)
* **public float xrLayerRadius**: Reference to the external surface object. Radius in metres of the equirect sphere. 0 makes it infinite, which is what 360 video normally wants — the viewer then sits at its centre no matter where they walk. Ignored by the Quad projection. (Platforms: Android, OpenXR)
* **public List \<string\> url**: List of the URLs for the stream.
* **public list \<string\> urlMimeTypes**: List of the HISPlayerMimeTypes attached to each URL from the url list.
* **public list \<string\> extSubtitleUrl**: List of the URLs for the external subtitle attached to each URL from the url list.
Expand All @@ -38,6 +44,11 @@ The following public APIs are provided by **HISPlayerManager**:
* **NONE**
* **ExternalSurface**

* **public enum HISPlayerXRLayerProjection**: Type of layer projection for external surface rendering:
* **Quad**
* **Equirect360**
* **Equirect180**

* **public enum HISPlayerStereoMode**: Type of stereoscopic mode for external surface rendering:
* **None**
* **LeftRight**
Expand Down
Binary file added image-6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions releases.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# HISPlayer Unity Android XR SDK Release Notes

##### September XX, 2026
- [**Added**] Support DRM L1 with External Surface. (OpenXR, AndroidXR only)
- [**Improvement**] Display watermark over External Surface. (OpenXR, AndroidXR only)

### Version 5.8.2
##### July 27, 2026
- [**Improvement**] Optimized Ambisonics support with HLS/DASH streaming.
Expand Down
102 changes: 16 additions & 86 deletions rendermodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,104 +2,34 @@

HISPlayer supports multiple rendering modes to suit different use cases and platforms. The recommended mode for XR/VR applications is **External Surface (Composition Layer)**, which leverages the OpenXR composition layer for optimal performance and latency. Other modes like **RenderTexture**, **Material**, and **RawImage** are also available for 2D UI or non‑XR scenarios.

## External Surface (Composition Layer)
## External Surface

This mode uses **XR Composition Layers** to render video directly onto a composition layer, bypassing the main render pipeline for improved performance in XR headsets. It is the preferred choice for immersive VR experiences on Android (e.g., Galaxy XR, Meta Quest, Pico, etc.).
This mode uses **XR Video Layers**, which are created and managed inside the HISPlayer SDK to render video directly onto an Android Surface, bypassing the main render pipeline for improved performance in open XR headsets. It is the preferred choice for immersive VR experiences on Android (e.g., Galaxy XR, Meta Quest, Pico, etc.).

### Setup

1. Create an empty GameObject.
2. Attach the following components to it:
- **Composition Layer** (from the XR Composition Layers package)
- **Source Textures** (from the XR Composition Layers package). *The width (W) and height (H) values of the resolution must not be zero*.

<p align="center">
<img src="image-4.png" alt="texto" width="50%" style="height: auto;">
<img src="image-7.png" width="400" />
</p>

3. In your script (inheriting from `HISPlayerManager`) set the `renderMode` to `HISPlayerRenderMode.ExternalSurface` in the `MultiStreamProperties`.
> Important: There is no need to add any additional components. The HISPlayer SDK will automatically add the XR Video Layer component internally.

2. In your script (inheriting from `HISPlayerManager`), set the `renderMode` to `HISPlayerRenderMode.ExternalSurface` in the `MultiStreamProperties`.

<p align="center">
<img src="https://github.com/user-attachments/assets/e0c0e141-e3df-4c06-8c1b-241ba5e6615a" alt="texto" width="50%" style="height: auto;" />
<img src="image-6.png" alt="External Surface render mode setting" width="450" style="height: auto;" />
</p>

4. Implement a coroutine to retrieve the native Android surface from the `CompositionLayer` and assign it to the `externalSurface` property of your stream. <br>
The resolution of the Source Textures cannot be zero, so a minimum value must be enforced. If the resolution is zero, acquiring the Android surface will fail.
The following example shows how to do this:

```C#
using Unity.XR.CompositionLayers;
using Unity.XR.CompositionLayers.Extensions;

[SerializeField] private GameObject renderScreen;
private IEnumerator SetUpExternalSurface()
{
CompositionLayer layer = renderScreen.GetComponent<CompositionLayer>();

IntPtr surfacePtr = IntPtr.Zero;
int maxAttempts = 10;
int attempts = 0;

SetExternalSurfaceSize(renderScreen, 1, 1);

while (surfacePtr == IntPtr.Zero && attempts < maxAttempts)
{
yield return new WaitForEndOfFrame();

int layerId = layer.GetInstanceID();
surfacePtr = UnityEngine.XR.OpenXR.CompositionLayers.OpenXRLayerUtility.GetLayerAndroidSurfaceObject(layerId);

attempts++;
}

if (surfacePtr != IntPtr.Zero)
{
multiStreamProperties[streamIndex].externalSurface = surfacePtr;

}
SetUpPlayer();
}

private void SetExternalSurfaceSize(GameObject renderScreen, int width, int height)
{
TexturesExtension sourceTexturesComponent = renderScreen.GetComponent<TexturesExtension>();
if (sourceTexturesComponent != null)
{
sourceTexturesComponent.Resolution = new Vector2(width, height);
}
else
{
Debug.LogError("[Error] TexturesExtension component is not attached.");
}
}
```

> Important: SetUpPlayer() must be called after the surface is assigned and before using any other HISPlayer APIs. Additionally, the resolution of the **Source Textures** must match the original video resolution.

### Retrieving the Android Surface

The script uses the `OpenXRLayerUtility.GetLayerAndroidSurfaceObject()` method to obtain the native surface pointer from the `CompositionLayer` and assigns it to the `externalSurface` field before calling `SetUpPlayer()`.

### Updating the Resolution of Source Textures
The resolution of the **Source Textures** must match the original video resolution. Otherwise, the output video frames will be cropped or display garbage data. Therefore, the width (W) and height (H) must be updated whenever the original video resolution changes. Please override the `void EventVideoSizeChange(HISPlayerEventInfo eventInfo)` function and set the new resolution values within it.

```C#
protected override void EventVideoSizeChange(HISPlayerEventInfo eventInfo)
{
if (!isPlaybackReady)
{
videoTracks = GetTracks(streamIndex);
}

if (videoTracks != null)
{
int width = (int)eventInfo.param1;
int height = (int)eventInfo.param2;

SetExternalSurfaceSize(renderScreen, width, height);
}
}
```
3. Set the properties related to External Surface:
* **Xr Layer Transform**: Use this property to set the position and size of the video. Assign the GameObject on which the video will be displayed (RenderScreen). This is a mandatory property.
* **Xr Layer Order**: Composition order, default is 1. A negative value puts the video below the scene. Do not set it to 0. <u>*If multiple streamProperties are used, this value should not be the same for each stream. If **Xr Layer Stereo Mode** is not **None**, each stream uses two layers (left and right eye), so an N + 1 layer order value is used internally — so be careful when setting this value across multiple streamProperties.*</u>
* **Xr Layer Projection**: The shape type used to display the video. [Quad, Equirect360 or Equirect180]
* **Xr Layer Stereo Mode**: The stereo mode. [None, LeftRight or TopBottom]
* **Xr Layer Match Video Aspect**: Keeps the original source video's aspect ratio within the **Xr Layer Transform** region. **Quad only**
* **Xr Layer Radius**: Radius of the Equirect screen. 0 means an infinite sphere. **Equirect 360/180 only**

> Important: Do not set the `StreamProperties.externalSurface` property. This property is set automatically by the SDK.


## RenderTexture
Expand Down
5 changes: 4 additions & 1 deletion setup-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,10 @@ This scene demonstrates high-resolution video playback using **Render Texture**

#### 360° Scene

This scene demonstrates 360° video playback using **RenderTexture** render mode. The `RenderScreen` GameObject uses a **Sphere** as its Mesh Filter and only has a **Mesh Renderer**. This is the recommended configuration for 360° video.
This scene demonstrates 360° video playback using **External Surface** render mode. Set the **Xr Layer Projection** option to **Equirect 360**.
<p align="center">
<img src="image-8.png" width="400"/>
</p>

#### Ambisonic Audio Scene

Expand Down
7 changes: 7 additions & 0 deletions stereoscopic.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

HISPlayer SDK supports stereoscopic Side-By-Side (Left/Right) and Top/Bottom video rendering. **MV-HEVC** video codec is also supported with maximum resolution 1080p for smooth playback.

## External Surface Render Mode
Set the **Xr Layer Stereo Mode** option to **None**, **Left Right**, or **Top Bottom**, depending on your stereoscopic video format, in the HISPlayer multistream properties.

<p align="center">
<img src="image-9.png" width="400" />
</p>

## Material / RenderTexture / RawImage Render Mode
Use **Material** or **RenderTexture** Render Mode in HISPlayer multistream properties, after creating your RenderTexture and Material, please attach **HISPlayerStereoscopicShader** shader to your Material.

Expand Down