# Send raw data You can feed your own video, audio, and share frames into a session, which is useful for headless apps with no camera or microphone, or to send processed media. ## Send raw video data To send raw or processed video as the local user's camera: 1. Implement an instance of `IZoomVideoSDKVideoSource`. 2. Assign it to `externalVideoSource` on the `ZoomVideoSDKSessionContext` before joining a session. 3. Obtain the `IZoomVideoSDKVideoSender` from the `onInitialize` callback. 4. Call `sendVideoFrame` from `onStartSend` to send frames. ```cpp ZoomVideoSDKVideoSource* pVirtualVideoSource = new ZoomVideoSDKVideoSource(); session_context.externalVideoSource = pVirtualVideoSource; void ZoomVideoSDKVideoSource::onInitialize(IZoomVideoSDKVideoSender* sender, IVideoSDKVector* support_cap_list, VideoSourceCapability& suggest_cap) { m_pSender = sender; } void ZoomVideoSDKVideoSource::onPropertyChange(IVideoSDKVector* support_cap_list, VideoSourceCapability suggest_cap) {} void ZoomVideoSDKVideoSource::onStartSend() { // Send a frame buffer of raw video data. m_pSender->sendVideoFrame(frameBuffer, width, height, frameLength, rotation); } void ZoomVideoSDKVideoSource::onStopSend() {} void ZoomVideoSDKVideoSource::onUninitialized() {} ``` In the `onInitialize` callback: - The `support_cap_list` parameter is the supported capability list. It combines the supported resolution of the session and the device into a list of supported capabilities. - The `suggest_cap` parameter is the suggested capability. It combines the maximum capability of the session and the device to get the real maximum as the suggested capability. `sendVideoFrame` accepts an optional `FrameDataFormat` argument that defaults to `FrameDataFormat_I420_FULL`. ## Pre-process raw video data To modify the local camera frames before they are sent, rather than supplying frames from scratch, implement `IZoomVideoSDKVideoSourcePreProcessor` and assign it to `preProcessor` on the `ZoomVideoSDKSessionContext`. The SDK passes each frame to `onPreProcessRawData`. ```cpp void CExampleVideoSourcePreProcessor::onPreProcessRawData(YUVProcessDataI420* rawData) { unsigned int width = rawData->GetWidth(); unsigned int height = rawData->GetHeight(); char* yBuffer = rawData->GetYBuffer(); char* uBuffer = rawData->GetUBuffer(); char* vBuffer = rawData->GetVBuffer(); // Modify the buffers in place. } ``` ## Send raw audio data To send raw or processed audio as the local user's microphone: 1. Implement an instance of `IZoomVideoSDKVirtualAudioMic`. 2. Assign it to `virtualAudioMic` on the `ZoomVideoSDKSessionContext` before joining a session. Set `audioOption.connect = true` and `audioOption.mute = false`. 3. Obtain the `IZoomVideoSDKAudioSender` from the `onMicInitialize` callback. 4. Call `Send` from `onMicStartSend` to send frames. ```cpp ZoomVideoSDKVirtualAudioMic* pVirtualMic = new ZoomVideoSDKVirtualAudioMic(); session_context.virtualAudioMic = pVirtualMic; session_context.audioOption.connect = true; session_context.audioOption.mute = false; void ZoomVideoSDKVirtualAudioMic::onMicInitialize(IZoomVideoSDKAudioSender* rawdata_sender) { // Store rawdata_sender for later use. m_pSender = rawdata_sender; } void ZoomVideoSDKVirtualAudioMic::onMicStartSend() { // You can now send audio. m_pSender->Send(rawData, lengthInBytes, sampleRate); } void ZoomVideoSDKVirtualAudioMic::onMicStopSend() {} void ZoomVideoSDKVirtualAudioMic::onMicUninitialized() {} ``` `Send` takes 16-bit PCM audio. The `data_length` must be even, and `sample_rate` accepts an optional `ZoomVideoSDKAudioChannel` argument that defaults to `ZoomVideoSDKAudioChannel_Mono`. ## Send raw share data To send raw screen share frames: 1. Implement an instance of `IZoomVideoSDKShareSource`. 2. Pass it to `startSharingExternalSource` on `IZoomVideoSDKShareHelper` while in a session. 3. Call `sendShareFrame` from `onShareSendStarted` to send frames. ```cpp ZoomVideoSDKShareSource* pVirtualShareSource = new ZoomVideoSDKShareSource(); m_pVideoSDK->getShareHelper()->startSharingExternalSource(pVirtualShareSource); void ZoomVideoSDKShareSource::onShareSendStarted(IZoomVideoSDKShareSender* pSender) { pSender->sendShareFrame(frameBuffer, width, height, frameLength); } void ZoomVideoSDKShareSource::onShareSendStopped() {} ```