# Two Approaches to Custom UI: SDK-Rendered vs Self-Rendered

> **Skill**: Zoom Meeting SDK (Windows)  
> **Category**: Concepts  
> **Prerequisite**: [Custom UI Architecture](custom-ui-architecture.md), [Raw Video Capture](../examples/raw-video-capture.md)

## Overview

There are two fundamentally different ways to build a custom meeting UI with the Zoom SDK. Both require Custom UI mode (`ENABLE_CUSTOMIZED_UI_FLAG`), but they differ in who renders the video.

## Approach 1: SDK-Rendered (ICustomizedVideoContainer)

The SDK renders video into your window using Direct3D. You control layout, the SDK controls pixels.

### How it works
```
Your Win32 Window
  -> SDK creates child HWND inside it
    -> SDK renders video via D3D11 into child HWND
      -> You call SetPos(RECT) to position video elements
```

### You control
- Window creation, sizing, positioning
- Which participants are visible and where (`SetPos`)
- Active speaker vs gallery layout
- Your own UI controls (buttons, toolbar)
- Background color (`SetBkColor`)

### SDK controls
- Actual video decoding and rendering
- D3D pipeline
- Frame timing
- Video quality / resolution scaling

### Key APIs
- `CreateCustomizedUIMgr()` / `DestroyCustomizedUIMgr()`
- `ICustomizedUIMgr::CreateVideoContainer()` / `DestroyVideoContainer()`
- `ICustomizedVideoContainer::CreateVideoElement()`
- `IActiveVideoRenderElement::Start()` / `Stop()`
- `INormalVideoRenderElement::Subscribe(userId)`
- `IVideoRenderElement::SetPos(RECT)` / `Show()` / `Hide()`

### Best for
- Standard meeting applications
- Apps that need a meeting window with video
- Rapid development (less code)
- When you don't need pixel-level access

### Limitations
- No access to raw video frames
- Cannot apply custom filters/effects
- Cannot render video in your own graphics engine
- Cannot pop individual videos into separate windows (elements are regions within one container)
- Single rendering surface per container

---

## Approach 2: Self-Rendered (IZoomSDKRenderer + Raw Data)

You get raw YUV420 frames per participant and render them yourself. Maximum control.

### How it works
```
SDK decodes video internally
  -> IZoomSDKRendererDelegate::onRawDataFrameReceived(YUVRawDataI420*)
    -> You get raw pixel data (Y, U, V planes)
      -> You render with your own engine (D3D11, OpenGL, GDI, etc.)
```

### You control
- Everything from Approach 1, PLUS:
- Raw pixel access (YUV420 frames)
- Your own rendering pipeline (D3D11, OpenGL, Vulkan, GDI, etc.)
- Custom video processing (filters, watermarks, overlays, effects)
- Multiple separate windows per participant
- Picture-in-picture
- Recording/streaming with effects applied
- Any layout imaginable

### SDK provides
- Decoded video frames as `YUVRawDataI420*`
- Frame metadata (width, height, rotation)
- Per-participant subscription

### Key APIs
- `createRenderer()` — creates a renderer for one participant
- `IZoomSDKRenderer::setRawDataResolution()` — set quality
- `IZoomSDKRenderer::subscribe(userId)` — bind to participant
- `IZoomSDKRendererDelegate::onRawDataFrameReceived(YUVRawDataI420*)` — frame callback
- `IZoomSDKRendererDelegate::onRawDataStatusChanged(RawDataStatus)` — status changes
- Raw recording: `IMeetingRecordingController::StartRawRecording()`

### Best for
- Custom rendering engines
- Video processing / effects
- Multi-window layouts
- Recording with overlays
- Streaming applications
- Research / computer vision

### Limitations
- More code to write (you handle all rendering)
- Must convert YUV420 to RGB/BGRA for display
- Must manage frame buffers and timing
- Higher CPU usage if not GPU-accelerated
- Must call `StartRawRecording()` before frames flow

---

## Approach 3: Hybrid (Both Together)

You can combine both approaches in the same application:

```
Custom UI mode enabled
  |
  +-- ICustomizedVideoContainer for main meeting view
  |     (SDK renders, you layout)
  |
  +-- IZoomSDKRenderer for specific participants
        (raw frames for recording, processing, pop-out windows)
```

### Use cases
- Main meeting window uses SDK rendering (efficient, easy)
- Simultaneously capture raw frames for recording with watermarks
- Pop out a specific participant into a custom-rendered window
- Apply computer vision to one participant's feed while showing others normally

### How to combine
1. Initialize with `ENABLE_CUSTOMIZED_UI_FLAG`
2. Create `ICustomizedVideoContainer` for the main view
3. Also call `createRenderer()` + `subscribe()` for raw data on specific users
4. Both can run simultaneously

---

## Comparison Table

| Feature | SDK-Rendered | Self-Rendered | Hybrid |
|---------|-------------|---------------|--------|
| Raw pixel access | No | Yes | Yes (selected users) |
| Custom filters/effects | No | Yes | Yes (selected users) |
| Multiple windows | No (regions in 1 container) | Yes | Yes |
| Rendering effort | Minimal | High | Medium |
| CPU usage | Low (SDK uses D3D) | Higher (unless GPU) | Medium |
| Code complexity | Low | High | Medium |
| Layout flexibility | RECT regions | Unlimited | Mix |
| Active speaker tracking | Built-in (`VideoRenderElement_ACTIVE`) | Manual | Mix |
| Screen share display | Built-in (`ICustomizedShareRender`) | Manual from raw data | Mix |
| Time to implement | Hours | Days | Hours + targeted raw data |

---

## Decision Guide

**Use SDK-Rendered when:**
- You just need a meeting window with custom layout
- You want to add your own toolbar/controls around the video
- Development speed matters
- You don't need to touch the video pixels

**Use Self-Rendered when:**
- You need to apply effects/filters to video
- You're building a custom rendering engine
- You need participants in separate windows
- You're doing computer vision / ML on the video
- You need full pixel control

**Use Hybrid when:**
- You want the easy SDK rendering for the main view
- But also need raw frames for specific purposes (recording, one pop-out window, etc.)

---

**See also:**
- [Custom UI Architecture](custom-ui-architecture.md) — How SDK rendering works internally
- [Custom UI Video Rendering Example](../examples/custom-ui-video-rendering.md) — SDK-rendered approach
- [Raw Video Capture](../examples/raw-video-capture.md) — Self-rendered approach
