::max)();
+
+
+struct EncodedVideoFrameInfo;
+
+struct ExtensionContext {
+ /** Whether uid is valid.
+ */
+ bool isValid;
+ /** Default 0 when "isValid" is false
+ * Local user is 0 and remote user great than 0 when "isValid" is true
+ */
+ uid_t uid;
+ /** current extension's provider name
+ */
+ const char *providerName;
+ /** current extension's name
+ */
+ const char *extensionName;
+ ExtensionContext():isValid(false), uid(0), providerName(NULL), extensionName(NULL) {}
+};
+
+
+/**
+* Video source types definition.
+**/
+enum VIDEO_SOURCE_TYPE {
+ /** Video captured by the camera.
+ */
+ VIDEO_SOURCE_CAMERA_PRIMARY = 0,
+ VIDEO_SOURCE_CAMERA = VIDEO_SOURCE_CAMERA_PRIMARY,
+ /** Video captured by the secondary camera.
+ */
+ VIDEO_SOURCE_CAMERA_SECONDARY = 1,
+ /** Video for screen sharing.
+ */
+ VIDEO_SOURCE_SCREEN_PRIMARY = 2,
+ VIDEO_SOURCE_SCREEN = VIDEO_SOURCE_SCREEN_PRIMARY,
+ /** Video for secondary screen sharing.
+ */
+ VIDEO_SOURCE_SCREEN_SECONDARY = 3,
+ /** Not define.
+ */
+ VIDEO_SOURCE_CUSTOM = 4,
+ /** Video for media player sharing.
+ */
+ VIDEO_SOURCE_MEDIA_PLAYER = 5,
+ /** Video for png image.
+ */
+ VIDEO_SOURCE_RTC_IMAGE_PNG = 6,
+ /** Video for png image.
+ */
+ VIDEO_SOURCE_RTC_IMAGE_JPEG = 7,
+ /** Video for png image.
+ */
+ VIDEO_SOURCE_RTC_IMAGE_GIF = 8,
+ /** Remote video received from network.
+ */
+ VIDEO_SOURCE_REMOTE = 9,
+ /** Video for transcoded.
+ */
+ VIDEO_SOURCE_TRANSCODED = 10,
+
+ /** Video captured by the third camera.
+ */
+ VIDEO_SOURCE_CAMERA_THIRD = 11,
+ /** Video captured by the fourth camera.
+ */
+ VIDEO_SOURCE_CAMERA_FOURTH = 12,
+ /** Video for third screen sharing.
+ */
+ VIDEO_SOURCE_SCREEN_THIRD = 13,
+ /** Video for fourth screen sharing.
+ */
+ VIDEO_SOURCE_SCREEN_FOURTH = 14,
+
+ VIDEO_SOURCE_UNKNOWN = 100
+};
+
+/**
+ * Audio routes.
+ */
+enum AudioRoute
+{
+ /**
+ * -1: The default audio route.
+ */
+ ROUTE_DEFAULT = -1,
+ /**
+ * The headset.
+ */
+ ROUTE_HEADSET = 0,
+ /**
+ * The earpiece.
+ */
+ ROUTE_EARPIECE = 1,
+ /**
+ * The headset with no microphone.
+ */
+ ROUTE_HEADSETNOMIC = 2,
+ /**
+ * The speakerphone.
+ */
+ ROUTE_SPEAKERPHONE = 3,
+ /**
+ * The loudspeaker.
+ */
+ ROUTE_LOUDSPEAKER = 4,
+ /**
+ * The Bluetooth headset.
+ */
+ ROUTE_HEADSETBLUETOOTH = 5,
+ /**
+ * The USB
+ */
+ ROUTE_USB = 6,
+ /**
+ * The HDMI
+ */
+ ROUTE_HDMI = 7,
+ /**
+ * The DISPLAYPORT
+ */
+ ROUTE_DISPLAYPORT = 8,
+ /**
+ * The AIRPLAY
+ */
+ ROUTE_AIRPLAY = 9,
+ /**
+ * The BLUETOOTH Speaker via a2dp
+ */
+ ROUTE_BLUETOOTH_SPEAKER = 10,
+};
+
+/**
+ * Bytes per sample
+ */
+enum BYTES_PER_SAMPLE {
+ /**
+ * two bytes per sample
+ */
+ TWO_BYTES_PER_SAMPLE = 2,
+};
+
+struct AudioParameters {
+ int sample_rate;
+ size_t channels;
+ size_t frames_per_buffer;
+
+ AudioParameters()
+ : sample_rate(0),
+ channels(0),
+ frames_per_buffer(0) {}
+};
+
+/**
+ * The use mode of the audio data.
+ */
+enum RAW_AUDIO_FRAME_OP_MODE_TYPE {
+ /** 0: Read-only mode: Users only read the data from `AudioFrame` without modifying anything.
+ * For example, when users acquire the data with the Agora SDK, then start the media push.
+ */
+ RAW_AUDIO_FRAME_OP_MODE_READ_ONLY = 0,
+
+ /** 2: Read and write mode: Users read the data from `AudioFrame`, modify it, and then play it.
+ * For example, when users have their own audio-effect processing module and perform some voice pre-processing, such as a voice change.
+ */
+ RAW_AUDIO_FRAME_OP_MODE_READ_WRITE = 2,
+};
+
+} // namespace rtc
+
+namespace media {
+ /**
+ * The type of media device.
+ */
+enum MEDIA_SOURCE_TYPE {
+ /**
+ * 0: The audio playback device.
+ */
+ AUDIO_PLAYOUT_SOURCE = 0,
+ /**
+ * 1: Microphone.
+ */
+ AUDIO_RECORDING_SOURCE = 1,
+ /**
+ * 2: Video captured by primary camera.
+ */
+ PRIMARY_CAMERA_SOURCE = 2,
+ /**
+ * 3: Video captured by secondary camera.
+ */
+ SECONDARY_CAMERA_SOURCE = 3,
+ /**
+ * 4: Video captured by primary screen capturer.
+ */
+ PRIMARY_SCREEN_SOURCE = 4,
+ /**
+ * 5: Video captured by secondary screen capturer.
+ */
+ SECONDARY_SCREEN_SOURCE = 5,
+ /**
+ * 6: Video captured by custom video source.
+ */
+ CUSTOM_VIDEO_SOURCE = 6,
+ /**
+ * 7: Video for media player sharing.
+ */
+ MEDIA_PLAYER_SOURCE = 7,
+ /**
+ * 8: Video for png image.
+ */
+ RTC_IMAGE_PNG_SOURCE = 8,
+ /**
+ * 9: Video for jpeg image.
+ */
+ RTC_IMAGE_JPEG_SOURCE = 9,
+ /**
+ * 10: Video for gif image.
+ */
+ RTC_IMAGE_GIF_SOURCE = 10,
+ /**
+ * 11: Remote video received from network.
+ */
+ REMOTE_VIDEO_SOURCE = 11,
+ /**
+ * 12: Video for transcoded.
+ */
+ TRANSCODED_VIDEO_SOURCE = 12,
+ /**
+ * 100: Internal Usage only.
+ */
+ UNKNOWN_MEDIA_SOURCE = 100
+};
+/** Definition of contentinspect
+ */
+#define MAX_CONTENT_INSPECT_MODULE_COUNT 32
+enum CONTENT_INSPECT_RESULT {
+ CONTENT_INSPECT_NEUTRAL = 1,
+ CONTENT_INSPECT_SEXY = 2,
+ CONTENT_INSPECT_PORN = 3,
+};
+
+enum CONTENT_INSPECT_TYPE {
+/**
+ * (Default) content inspect type invalid
+ */
+CONTENT_INSPECT_INVALID = 0,
+/**
+ * @deprecated
+ * Content inspect type moderation
+ */
+CONTENT_INSPECT_MODERATION __deprecated = 1,
+/**
+ * Content inspect type supervise
+ */
+CONTENT_INSPECT_SUPERVISION = 2,
+/**
+ * Content inspect type image moderation
+ */
+CONTENT_INSPECT_IMAGE_MODERATION = 3
+};
+
+struct ContentInspectModule {
+ /**
+ * The content inspect module type.
+ */
+ CONTENT_INSPECT_TYPE type;
+ /**The content inspect frequency, default is 0 second.
+ * the frequency <= 0 is invalid.
+ */
+ unsigned int interval;
+ ContentInspectModule() {
+ type = CONTENT_INSPECT_INVALID;
+ interval = 0;
+ }
+};
+/** Definition of ContentInspectConfig.
+ */
+struct ContentInspectConfig {
+ const char* extraInfo;
+
+ /**The content inspect modules, max length of modules is 32.
+ * the content(snapshot of send video stream, image) can be used to max of 32 types functions.
+ */
+ ContentInspectModule modules[MAX_CONTENT_INSPECT_MODULE_COUNT];
+ /**The content inspect module count.
+ */
+ int moduleCount;
+ ContentInspectConfig& operator=(const ContentInspectConfig& rth)
+ {
+ extraInfo = rth.extraInfo;
+ moduleCount = rth.moduleCount;
+ memcpy(&modules, &rth.modules, MAX_CONTENT_INSPECT_MODULE_COUNT * sizeof(ContentInspectModule));
+ return *this;
+ }
+ ContentInspectConfig() :extraInfo(NULL), moduleCount(0){}
+};
+
+namespace base {
+
+typedef void* view_t;
+
+typedef const char* user_id_t;
+
+static const uint8_t kMaxCodecNameLength = 50;
+
+/**
+ * The definition of the PacketOptions struct, which contains infomation of the packet
+ * in the RTP (Real-time Transport Protocal) header.
+ */
+struct PacketOptions {
+ /**
+ * The timestamp of the packet.
+ */
+ uint32_t timestamp;
+ // Audio level indication.
+ uint8_t audioLevelIndication;
+ PacketOptions()
+ : timestamp(0),
+ audioLevelIndication(127) {}
+};
+
+/**
+ * The detailed information of the incoming audio encoded frame.
+ */
+
+struct AudioEncodedFrameInfo {
+ /**
+ * The send time of the packet.
+ */
+ uint64_t sendTs;
+ /**
+ * The codec of the packet.
+ */
+ uint8_t codec;
+ AudioEncodedFrameInfo()
+ : sendTs(0),
+ codec(0) {}
+};
+
+/**
+ * The detailed information of the incoming audio frame in the PCM format.
+ */
+struct AudioPcmFrame {
+ /**
+ * The buffer size of the PCM audio frame.
+ */
+ OPTIONAL_ENUM_SIZE_T {
+ // Stereo, 32 kHz, 60 ms (2 * 32 * 60)
+ /**
+ * The max number of the samples of the data.
+ *
+ * When the number of audio channel is two, the sample rate is 32 kHZ,
+ * the buffer length of the data is 60 ms, the number of the samples of the data is 3840 (2 x 32 x 60).
+ */
+ kMaxDataSizeSamples = 3840,
+ /** The max number of the bytes of the data. */
+ kMaxDataSizeBytes = kMaxDataSizeSamples * sizeof(int16_t),
+ };
+
+ /** The timestamp (ms) of the audio frame.
+ */
+ int64_t capture_timestamp;
+ /** The number of samples per channel.
+ */
+ size_t samples_per_channel_;
+ /** The sample rate (Hz) of the audio data.
+ */
+ int sample_rate_hz_;
+ /** The channel number.
+ */
+ size_t num_channels_;
+ /** The number of bytes per sample.
+ */
+ rtc::BYTES_PER_SAMPLE bytes_per_sample;
+ /** The audio frame data. */
+ int16_t data_[kMaxDataSizeSamples];
+
+ AudioPcmFrame& operator=(const AudioPcmFrame& src) {
+ if(this == &src) {
+ return *this;
+ }
+
+ this->capture_timestamp = src.capture_timestamp;
+ this->samples_per_channel_ = src.samples_per_channel_;
+ this->sample_rate_hz_ = src.sample_rate_hz_;
+ this->bytes_per_sample = src.bytes_per_sample;
+ this->num_channels_ = src.num_channels_;
+
+ size_t length = src.samples_per_channel_ * src.num_channels_;
+ if (length > kMaxDataSizeSamples) {
+ length = kMaxDataSizeSamples;
+ }
+
+ memcpy(this->data_, src.data_, length * sizeof(int16_t));
+
+ return *this;
+ }
+
+ AudioPcmFrame()
+ : capture_timestamp(0),
+ samples_per_channel_(0),
+ sample_rate_hz_(0),
+ num_channels_(0),
+ bytes_per_sample(rtc::TWO_BYTES_PER_SAMPLE) {
+ memset(data_, 0, sizeof(data_));
+ }
+
+ AudioPcmFrame(const AudioPcmFrame& src)
+ : capture_timestamp(src.capture_timestamp),
+ samples_per_channel_(src.samples_per_channel_),
+ sample_rate_hz_(src.sample_rate_hz_),
+ num_channels_(src.num_channels_),
+ bytes_per_sample(src.bytes_per_sample) {
+ size_t length = src.samples_per_channel_ * src.num_channels_;
+ if (length > kMaxDataSizeSamples) {
+ length = kMaxDataSizeSamples;
+ }
+
+ memcpy(this->data_, src.data_, length * sizeof(int16_t));
+ }
+};
+
+/** Audio dual-mono output mode
+ */
+enum AUDIO_DUAL_MONO_MODE {
+ /**< ChanLOut=ChanLin, ChanRout=ChanRin */
+ AUDIO_DUAL_MONO_STEREO = 0,
+ /**< ChanLOut=ChanRout=ChanLin */
+ AUDIO_DUAL_MONO_L = 1,
+ /**< ChanLOut=ChanRout=ChanRin */
+ AUDIO_DUAL_MONO_R = 2,
+ /**< ChanLout=ChanRout=(ChanLin+ChanRin)/2 */
+ AUDIO_DUAL_MONO_MIX = 3
+};
+/**
+ * The audio frame observer.
+ */
+class IAudioFrameObserver {
+ public:
+ /**
+ * Occurs when each time the player receives an audio frame.
+ *
+ * After registering the audio frame observer,
+ * the callback occurs when each time the player receives an audio frame,
+ * reporting the detailed information of the audio frame.
+ * @param frame The detailed information of the audio frame. See {@link AudioPcmFrame}.
+ */
+ virtual void onFrame(AudioPcmFrame* frame) = 0;
+ virtual ~IAudioFrameObserver() {}
+};
+
+/**
+ * Video pixel formats.
+ */
+enum VIDEO_PIXEL_FORMAT {
+ /**
+ * 0: Default format.
+ */
+ VIDEO_PIXEL_DEFAULT = 0,
+ /**
+ * 1: I420.
+ */
+ VIDEO_PIXEL_I420 = 1,
+ /**
+ * 2: BGRA.
+ */
+ VIDEO_PIXEL_BGRA = 2,
+ /**
+ * 3: NV21.
+ */
+ VIDEO_PIXEL_NV21 = 3,
+ /**
+ * 4: RGBA.
+ */
+ VIDEO_PIXEL_RGBA = 4,
+ /**
+ * 8: NV12.
+ */
+ VIDEO_PIXEL_NV12 = 8,
+ /**
+ * 10: GL_TEXTURE_2D
+ */
+ VIDEO_TEXTURE_2D = 10,
+ /**
+ * 11: GL_TEXTURE_OES
+ */
+ VIDEO_TEXTURE_OES = 11,
+ /*
+ 12: pixel format for iOS CVPixelBuffer NV12
+ */
+ VIDEO_CVPIXEL_NV12 = 12,
+ /*
+ 13: pixel format for iOS CVPixelBuffer I420
+ */
+ VIDEO_CVPIXEL_I420 = 13,
+ /*
+ 14: pixel format for iOS CVPixelBuffer BGRA
+ */
+ VIDEO_CVPIXEL_BGRA = 14,
+ /**
+ * 16: I422.
+ */
+ VIDEO_PIXEL_I422 = 16,
+};
+
+/**
+ * The video display mode.
+ */
+enum RENDER_MODE_TYPE {
+ /**
+ * 1: Uniformly scale the video until it fills the visible boundaries
+ * (cropped). One dimension of the video may have clipped contents.
+ */
+ RENDER_MODE_HIDDEN = 1,
+ /**
+ * 2: Uniformly scale the video until one of its dimension fits the boundary
+ * (zoomed to fit). Areas that are not filled due to the disparity in the
+ * aspect ratio will be filled with black.
+ */
+ RENDER_MODE_FIT = 2,
+ /**
+ * @deprecated
+ * 3: This mode is deprecated.
+ */
+ RENDER_MODE_ADAPTIVE __deprecated = 3,
+};
+
+/**
+ * The camera video source type
+ */
+enum CAMERA_VIDEO_SOURCE_TYPE {
+ /**
+ * 0: the video frame comes from the front camera
+ */
+ CAMERA_SOURCE_FRONT = 0,
+ /**
+ * 1: the video frame comes from the back camera
+ */
+ CAMERA_SOURCE_BACK = 1,
+ /**
+ * 1: the video frame source is unsepcified
+ */
+ VIDEO_SOURCE_UNSPECIFIED = 2,
+};
+
+/**
+ * The definition of the ExternalVideoFrame struct.
+ */
+struct ExternalVideoFrame {
+ ExternalVideoFrame()
+ : type(VIDEO_BUFFER_RAW_DATA),
+ format(VIDEO_PIXEL_DEFAULT),
+ buffer(NULL),
+ stride(0),
+ height(0),
+ cropLeft(0),
+ cropTop(0),
+ cropRight(0),
+ cropBottom(0),
+ rotation(0),
+ timestamp(0),
+ eglContext(NULL),
+ eglType(EGL_CONTEXT10),
+ textureId(0),
+ fence_object(0),
+ metadata_buffer(NULL),
+ metadata_size(0),
+ alphaBuffer(NULL),
+ fillAlphaBuffer(false){}
+
+ /**
+ * The EGL context type.
+ */
+ enum EGL_CONTEXT_TYPE {
+ /**
+ * 0: When using the OpenGL interface (javax.microedition.khronos.egl.*) defined by Khronos
+ */
+ EGL_CONTEXT10 = 0,
+ /**
+ * 0: When using the OpenGL interface (android.opengl.*) defined by Android
+ */
+ EGL_CONTEXT14 = 1,
+ };
+
+ /**
+ * Video buffer types.
+ */
+ enum VIDEO_BUFFER_TYPE {
+ /**
+ * 1: Raw data.
+ */
+ VIDEO_BUFFER_RAW_DATA = 1,
+ /**
+ * 2: The same as VIDEO_BUFFER_RAW_DATA.
+ */
+ VIDEO_BUFFER_ARRAY = 2,
+ /**
+ * 3: The video buffer in the format of texture.
+ */
+ VIDEO_BUFFER_TEXTURE = 3,
+ };
+
+ /**
+ * The buffer type: #VIDEO_BUFFER_TYPE.
+ */
+ VIDEO_BUFFER_TYPE type;
+ /**
+ * The pixel format: #VIDEO_PIXEL_FORMAT
+ */
+ VIDEO_PIXEL_FORMAT format;
+ /**
+ * The video buffer.
+ */
+ void* buffer;
+ /**
+ * The line spacing of the incoming video frame (px). For
+ * texture, it is the width of the texture.
+ */
+ int stride;
+ /**
+ * The height of the incoming video frame.
+ */
+ int height;
+ /**
+ * [Raw data related parameter] The number of pixels trimmed from the left. The default value is
+ * 0.
+ */
+ int cropLeft;
+ /**
+ * [Raw data related parameter] The number of pixels trimmed from the top. The default value is
+ * 0.
+ */
+ int cropTop;
+ /**
+ * [Raw data related parameter] The number of pixels trimmed from the right. The default value is
+ * 0.
+ */
+ int cropRight;
+ /**
+ * [Raw data related parameter] The number of pixels trimmed from the bottom. The default value
+ * is 0.
+ */
+ int cropBottom;
+ /**
+ * [Raw data related parameter] The clockwise rotation information of the video frame. You can set the
+ * rotation angle as 0, 90, 180, or 270. The default value is 0.
+ */
+ int rotation;
+ /**
+ * The timestamp (ms) of the incoming video frame. An incorrect timestamp results in a frame loss or
+ * unsynchronized audio and video.
+ *
+ * Please refer to getAgoraCurrentMonotonicTimeInMs or getCurrentMonotonicTimeInMs
+ * to determine how to fill this filed.
+ */
+ long long timestamp;
+ /**
+ * [Texture-related parameter]
+ * When using the OpenGL interface (javax.microedition.khronos.egl.*) defined by Khronos, set EGLContext to this field.
+ * When using the OpenGL interface (android.opengl.*) defined by Android, set EGLContext to this field.
+ */
+ void *eglContext;
+ /**
+ * [Texture related parameter] Texture ID used by the video frame.
+ */
+ EGL_CONTEXT_TYPE eglType;
+ /**
+ * [Texture related parameter] Incoming 4 × 4 transformational matrix. The typical value is a unit matrix.
+ */
+ int textureId;
+ /**
+ * [Texture related parameter]
+ */
+ long long fence_object;
+ /**
+ * [Texture related parameter] Incoming 4 × 4 transformational matrix. The typical value is a unit matrix.
+ */
+ float matrix[16];
+ /**
+ * [Texture related parameter] The MetaData buffer.
+ * The default value is NULL
+ */
+ uint8_t* metadata_buffer;
+ /**
+ * [Texture related parameter] The MetaData size.
+ * The default value is 0
+ */
+ int metadata_size;
+ /**
+ * Indicates the alpha channel of current frame, which is consistent with the dimension of the video frame.
+ * The value range of each pixel is [0,255], where 0 represents the background; 255 represents the foreground.
+ * The default value is NULL.
+ */
+ uint8_t* alphaBuffer;
+ /**
+ * Extract alphaBuffer from bgra or rgba data. Set it true if you do not explicitly specify the alphabuffer.
+ * The default value is false
+ */
+ bool fillAlphaBuffer;
+};
+
+/**
+ * The definition of the VideoFrame struct.
+ */
+struct VideoFrame {
+ VideoFrame():
+ type(VIDEO_PIXEL_DEFAULT),
+ width(0),
+ height(0),
+ yStride(0),
+ uStride(0),
+ vStride(0),
+ yBuffer(NULL),
+ uBuffer(NULL),
+ vBuffer(NULL),
+ rotation(0),
+ renderTimeMs(0),
+ avsync_type(0),
+ metadata_buffer(NULL),
+ metadata_size(0),
+ sharedContext(0),
+ textureId(0),
+ fence_object(0),
+ alphaBuffer(NULL),
+ pixelBuffer(NULL){}
+ /**
+ * The video pixel format: #VIDEO_PIXEL_FORMAT.
+ */
+ VIDEO_PIXEL_FORMAT type;
+ /**
+ * The width of the video frame.
+ */
+ int width;
+ /**
+ * The height of the video frame.
+ */
+ int height;
+ /**
+ * The line span of Y buffer in the YUV data.
+ */
+ int yStride;
+ /**
+ * The line span of U buffer in the YUV data.
+ */
+ int uStride;
+ /**
+ * The line span of V buffer in the YUV data.
+ */
+ int vStride;
+ /**
+ * The pointer to the Y buffer in the YUV data.
+ */
+ uint8_t* yBuffer;
+ /**
+ * The pointer to the U buffer in the YUV data.
+ */
+ uint8_t* uBuffer;
+ /**
+ * The pointer to the V buffer in the YUV data.
+ */
+ uint8_t* vBuffer;
+ /**
+ * The clockwise rotation information of this frame. You can set it as 0, 90, 180 or 270.
+ */
+ int rotation;
+ /**
+ * The timestamp to render the video stream. Use this parameter for audio-video synchronization when
+ * rendering the video.
+ *
+ * @note This parameter is for rendering the video, not capturing the video.
+ */
+ int64_t renderTimeMs;
+ /**
+ * The type of audio-video synchronization.
+ */
+ int avsync_type;
+ /**
+ * [Texture related parameter] The MetaData buffer.
+ * The default value is NULL
+ */
+ uint8_t* metadata_buffer;
+ /**
+ * [Texture related parameter] The MetaData size.
+ * The default value is 0
+ */
+ int metadata_size;
+ /**
+ * [Texture related parameter], egl context.
+ */
+ void* sharedContext;
+ /**
+ * [Texture related parameter], Texture ID used by the video frame.
+ */
+ int textureId;
+ /**
+ * [Texture related parameter]
+ */
+ long long fence_object;
+ /**
+ * [Texture related parameter], Incoming 4 × 4 transformational matrix.
+ */
+ float matrix[16];
+ /**
+ * Indicates the alpha channel of current frame, which is consistent with the dimension of the video frame.
+ * The value range of each pixel is [0,255], where 0 represents the background; 255 represents the foreground.
+ * The default value is NULL.
+ */
+ uint8_t* alphaBuffer;
+ /**
+ *The type of CVPixelBufferRef, for iOS and macOS only.
+ */
+ void* pixelBuffer;
+};
+
+/**
+ * The IVideoFrameObserver class.
+ */
+class IVideoFrameObserver {
+ public:
+ /**
+ * Occurs each time the player receives a video frame.
+ *
+ * After registering the video frame observer,
+ * the callback occurs each time the player receives a video frame to report the detailed information of the video frame.
+ * @param frame The detailed information of the video frame. See {@link VideoFrame}.
+ */
+ virtual void onFrame(const VideoFrame* frame) = 0;
+ virtual ~IVideoFrameObserver() {}
+ virtual bool isExternal() { return true; }
+ virtual VIDEO_PIXEL_FORMAT getVideoFormatPreference() { return VIDEO_PIXEL_DEFAULT; }
+};
+
+enum MEDIA_PLAYER_SOURCE_TYPE {
+ /**
+ * The real type of media player when use MEDIA_PLAYER_SOURCE_DEFAULT is decided by the
+ * type of SDK package. It is full feature media player in full-featured SDK, or simple
+ * media player in others.
+ */
+ MEDIA_PLAYER_SOURCE_DEFAULT,
+ /**
+ * Full featured media player is designed to support more codecs and media format, which
+ * requires more package size than simple player. If you need this player enabled, you
+ * might need to download a full-featured SDK.
+ */
+ MEDIA_PLAYER_SOURCE_FULL_FEATURED,
+ /**
+ * Simple media player with limit codec supported, which requires minimal package size
+ * requirement and is enabled by default
+ */
+ MEDIA_PLAYER_SOURCE_SIMPLE,
+};
+
+enum VIDEO_MODULE_POSITION {
+ POSITION_POST_CAPTURER = 1 << 0,
+ POSITION_PRE_RENDERER = 1 << 1,
+ POSITION_PRE_ENCODER = 1 << 2,
+};
+
+} // namespace base
+
+/**
+ * The IAudioFrameObserverBase class.
+ */
+class IAudioFrameObserverBase {
+ public:
+ /**
+ * Audio frame types.
+ */
+ enum AUDIO_FRAME_TYPE {
+ /**
+ * 0: 16-bit PCM.
+ */
+ FRAME_TYPE_PCM16 = 0,
+ };
+ enum { MAX_HANDLE_TIME_CNT = 10 };
+ /**
+ * The definition of the AudioFrame struct.
+ */
+ struct AudioFrame {
+ /**
+ * The audio frame type: #AUDIO_FRAME_TYPE.
+ */
+ AUDIO_FRAME_TYPE type;
+ /**
+ * The number of samples per channel in this frame.
+ */
+ int samplesPerChannel;
+ /**
+ * The number of bytes per sample: #BYTES_PER_SAMPLE
+ */
+ agora::rtc::BYTES_PER_SAMPLE bytesPerSample;
+ /**
+ * The number of audio channels (data is interleaved, if stereo).
+ * - 1: Mono.
+ * - 2: Stereo.
+ */
+ int channels;
+ /**
+ *The number of samples per channel in the audio frame.
+ */
+ int samplesPerSec;
+ /**
+ * The data buffer of the audio frame. When the audio frame uses a stereo channel, the data
+ * buffer is interleaved.
+ *
+ * Buffer data size: buffer = samples × channels × bytesPerSample.
+ */
+ void* buffer;
+ /**
+ * The timestamp to render the audio data.
+ *
+ * You can use this timestamp to restore the order of the captured audio frame, and synchronize
+ * audio and video frames in video scenarios, including scenarios where external video sources
+ * are used.
+ */
+ int64_t renderTimeMs;
+ /**
+ * The number of the audio track.
+ */
+ int audioTrackNumber;
+ /**
+ * A reserved parameter.
+ */
+ int avsync_type;
+
+ AudioFrame() : type(FRAME_TYPE_PCM16),
+ samplesPerChannel(0),
+ bytesPerSample(rtc::TWO_BYTES_PER_SAMPLE),
+ channels(0),
+ samplesPerSec(0),
+ buffer(NULL),
+ renderTimeMs(0),
+ audioTrackNumber(0),
+ avsync_type(0) {}
+ };
+
+ enum AUDIO_FRAME_POSITION {
+ AUDIO_FRAME_POSITION_NONE = 0x0000,
+ /** The position for observing the playback audio of all remote users after mixing
+ */
+ AUDIO_FRAME_POSITION_PLAYBACK = 0x0001,
+ /** The position for observing the recorded audio of the local user
+ */
+ AUDIO_FRAME_POSITION_RECORD = 0x0002,
+ /** The position for observing the mixed audio of the local user and all remote users
+ */
+ AUDIO_FRAME_POSITION_MIXED = 0x0004,
+ /** The position for observing the audio of a single remote user before mixing
+ */
+ AUDIO_FRAME_POSITION_BEFORE_MIXING = 0x0008,
+ /** The position for observing the ear monitoring audio of the local user
+ */
+ AUDIO_FRAME_POSITION_EAR_MONITORING = 0x0010,
+ /** The position for observing the before-publish audio of the local user
+ */
+ AUDIO_FRAME_POSITION_BEFORE_PUBLISH = 0x0020,
+ };
+
+ struct AudioParams {
+ /** The audio sample rate (Hz), which can be set as one of the following values:
+
+ - `8000`
+ - `16000` (Default)
+ - `32000`
+ - `44100 `
+ - `48000`
+ */
+ int sample_rate;
+
+ /* The number of audio channels, which can be set as either of the following values:
+
+ - `1`: Mono (Default)
+ - `2`: Stereo
+ */
+ int channels;
+
+ /* The use mode of the audio data. See AgoraAudioRawFrameOperationMode.
+ */
+ rtc::RAW_AUDIO_FRAME_OP_MODE_TYPE mode;
+
+ /** The number of samples. For example, set it as 1024 for RTMP or RTMPS
+ streaming.
+ */
+ int samples_per_call;
+
+ AudioParams() : sample_rate(0), channels(0), mode(rtc::RAW_AUDIO_FRAME_OP_MODE_READ_ONLY), samples_per_call(0) {}
+ AudioParams(int samplerate, int channel, rtc::RAW_AUDIO_FRAME_OP_MODE_TYPE type, int samplesPerCall) : sample_rate(samplerate), channels(channel), mode(type), samples_per_call(samplesPerCall) {}
+ };
+
+ public:
+ virtual ~IAudioFrameObserverBase() {}
+
+ /**
+ * Occurs when the recorded audio frame is received.
+ * @param channelId The channel name
+ * @param audioFrame The reference to the audio frame: AudioFrame.
+ * @return
+ * - true: The recorded audio frame is valid and is encoded and sent.
+ * - false: The recorded audio frame is invalid and is not encoded or sent.
+ */
+ virtual bool onRecordAudioFrame(const char* channelId, AudioFrame& audioFrame) = 0;
+ /**
+ * Occurs when the before-publishing audio frame is received.
+ * @param channelId The channel name
+ * @param audioFrame The reference to the audio frame: AudioFrame.
+ * @return
+ * - true: The recorded audio frame is valid and is encoded and sent.
+ * - false: The recorded audio frame is invalid and is not encoded or sent.
+ */
+ virtual bool onPublishAudioFrame(const char* channelId, AudioFrame& audioFrame) {
+ (void) channelId;
+ (void) audioFrame;
+ return true;
+ }
+ /**
+ * Occurs when the playback audio frame is received.
+ * @param channelId The channel name
+ * @param audioFrame The reference to the audio frame: AudioFrame.
+ * @return
+ * - true: The playback audio frame is valid and is encoded and sent.
+ * - false: The playback audio frame is invalid and is not encoded or sent.
+ */
+ virtual bool onPlaybackAudioFrame(const char* channelId, AudioFrame& audioFrame) = 0;
+ /**
+ * Occurs when the mixed audio data is received.
+ * @param channelId The channel name
+ * @param audioFrame The reference to the audio frame: AudioFrame.
+ * @return
+ * - true: The mixed audio data is valid and is encoded and sent.
+ * - false: The mixed audio data is invalid and is not encoded or sent.
+ */
+ virtual bool onMixedAudioFrame(const char* channelId, AudioFrame& audioFrame) = 0;
+ /**
+ * Occurs when the ear monitoring audio frame is received.
+ * @param audioFrame The reference to the audio frame: AudioFrame.
+ * @return
+ * - true: The ear monitoring audio data is valid and is encoded and sent.
+ * - false: The ear monitoring audio data is invalid and is not encoded or sent.
+ */
+ virtual bool onEarMonitoringAudioFrame(AudioFrame& audioFrame) = 0;
+ /**
+ * Occurs when the before-mixing playback audio frame is received.
+ * @param channelId The channel name
+ * @param userId ID of the remote user.
+ * @param audioFrame The reference to the audio frame: AudioFrame.
+ * @return
+ * - true: The before-mixing playback audio frame is valid and is encoded and sent.
+ * - false: The before-mixing playback audio frame is invalid and is not encoded or sent.
+ */
+ virtual bool onPlaybackAudioFrameBeforeMixing(const char* channelId, base::user_id_t userId, AudioFrame& audioFrame) {
+ (void) channelId;
+ (void) userId;
+ (void) audioFrame;
+ return true;
+ }
+
+ /**
+ * Sets the frame position for the audio observer.
+ * @return A bit mask that controls the frame position of the audio observer.
+ * @note - Use '|' (the OR operator) to observe multiple frame positions.
+ *
+ * After you successfully register the audio observer, the SDK triggers this callback each time it receives a audio frame. You can determine which position to observe by setting the return value.
+ * The SDK provides 4 positions for observer. Each position corresponds to a callback function:
+ * - `AUDIO_FRAME_POSITION_PLAYBACK (1 << 0)`: The position for playback audio frame is received, which corresponds to the \ref onPlaybackFrame "onPlaybackFrame" callback.
+ * - `AUDIO_FRAME_POSITION_RECORD (1 << 1)`: The position for record audio frame is received, which corresponds to the \ref onRecordFrame "onRecordFrame" callback.
+ * - `AUDIO_FRAME_POSITION_MIXED (1 << 2)`: The position for mixed audio frame is received, which corresponds to the \ref onMixedFrame "onMixedFrame" callback.
+ * - `AUDIO_FRAME_POSITION_BEFORE_MIXING (1 << 3)`: The position for playback audio frame before mixing is received, which corresponds to the \ref onPlaybackFrameBeforeMixing "onPlaybackFrameBeforeMixing" callback.
+ * @return The bit mask that controls the audio observation positions.
+ * See AUDIO_FRAME_POSITION.
+ */
+
+ virtual int getObservedAudioFramePosition() = 0;
+
+ /** Sets the audio playback format
+ **Note**:
+
+ - The SDK calculates the sample interval according to the `AudioParams`
+ you set in the return value of this callback and triggers the
+ `onPlaybackAudioFrame` callback at the calculated sample interval.
+ Sample interval (seconds) = `samplesPerCall`/(`sampleRate` × `channel`).
+ Ensure that the value of sample interval is equal to or greater than 0.01.
+
+ @return Sets the audio format. See AgoraAudioParams.
+ */
+ virtual AudioParams getPlaybackAudioParams() = 0;
+
+ virtual AudioParams getPublishAudioParams() {return AudioParams();}
+
+ /** Sets the audio recording format
+ **Note**:
+ - The SDK calculates the sample interval according to the `AudioParams`
+ you set in the return value of this callback and triggers the
+ `onRecordAudioFrame` callback at the calculated sample interval.
+ Sample interval (seconds) = `samplesPerCall`/(`sampleRate` × `channel`).
+ Ensure that the value of sample interval is equal to or greater than 0.01.
+
+ @return Sets the audio format. See AgoraAudioParams.
+ */
+ virtual AudioParams getRecordAudioParams() = 0;
+
+ /** Sets the audio mixing format
+ **Note**:
+ - The SDK calculates the sample interval according to the `AudioParams`
+ you set in the return value of this callback and triggers the
+ `onMixedAudioFrame` callback at the calculated sample interval.
+ Sample interval (seconds) = `samplesPerCall`/(`sampleRate` × `channel`).
+ Ensure that the value of sample interval is equal to or greater than 0.01.
+
+ @return Sets the audio format. See AgoraAudioParams.
+ */
+ virtual AudioParams getMixedAudioParams() = 0;
+
+ /** Sets the ear monitoring audio format
+ **Note**:
+ - The SDK calculates the sample interval according to the `AudioParams`
+ you set in the return value of this callback and triggers the
+ `onEarMonitoringAudioFrame` callback at the calculated sample interval.
+ Sample interval (seconds) = `samplesPerCall`/(`sampleRate` × `channel`).
+ Ensure that the value of sample interval is equal to or greater than 0.01.
+
+ @return Sets the audio format. See AgoraAudioParams.
+ */
+ virtual AudioParams getEarMonitoringAudioParams() = 0;
+};
+
+/**
+ * The IAudioFrameObserver class.
+ */
+class IAudioFrameObserver : public IAudioFrameObserverBase {
+ public:
+ using IAudioFrameObserverBase::onPlaybackAudioFrameBeforeMixing;
+ /**
+ * Occurs when the before-mixing playback audio frame is received.
+ * @param channelId The channel name
+ * @param uid ID of the remote user.
+ * @param audioFrame The reference to the audio frame: AudioFrame.
+ * @return
+ * - true: The before-mixing playback audio frame is valid and is encoded and sent.
+ * - false: The before-mixing playback audio frame is invalid and is not encoded or sent.
+ */
+ virtual bool onPlaybackAudioFrameBeforeMixing(const char* channelId, rtc::uid_t uid, AudioFrame& audioFrame) = 0;
+};
+
+struct AudioSpectrumData {
+ /**
+ * The audio spectrum data of audio.
+ */
+ const float *audioSpectrumData;
+ /**
+ * The data length of audio spectrum data.
+ */
+ int dataLength;
+
+ AudioSpectrumData() : audioSpectrumData(NULL), dataLength(0) {}
+ AudioSpectrumData(const float *data, int length) :
+ audioSpectrumData(data), dataLength(length) {}
+};
+
+struct UserAudioSpectrumInfo {
+ /**
+ * User ID of the speaker.
+ */
+ agora::rtc::uid_t uid;
+ /**
+ * The audio spectrum data of audio.
+ */
+ struct AudioSpectrumData spectrumData;
+
+ UserAudioSpectrumInfo () : uid(0), spectrumData() {}
+ UserAudioSpectrumInfo(agora::rtc::uid_t _uid, const float *data, int length) :
+ uid(_uid) { spectrumData.audioSpectrumData = data; spectrumData.dataLength = length; }
+};
+
+/**
+ * The IAudioSpectrumObserver class.
+ */
+class IAudioSpectrumObserver {
+public:
+ virtual ~IAudioSpectrumObserver() {}
+
+ /**
+ * Reports the audio spectrum of local audio.
+ *
+ * This callback reports the audio spectrum data of the local audio at the moment
+ * in the channel.
+ *
+ * You can set the time interval of this callback using \ref ILocalUser::enableAudioSpectrumMonitor "enableAudioSpectrumMonitor".
+ *
+ * @param data The audio spectrum data of local audio.
+ * - true: Processed.
+ * - false: Not processed.
+ */
+ virtual bool onLocalAudioSpectrum(const AudioSpectrumData& data) = 0;
+
+ /**
+ * Reports the audio spectrum of remote user.
+ *
+ * This callback reports the IDs and audio spectrum data of the loudest speakers at the moment
+ * in the channel.
+ *
+ * You can set the time interval of this callback using \ref ILocalUser::enableAudioSpectrumMonitor "enableAudioSpectrumMonitor".
+ *
+ * @param spectrums The pointer to \ref agora::media::UserAudioSpectrumInfo "UserAudioSpectrumInfo", which is an array containing
+ * the user ID and audio spectrum data for each speaker.
+ * - This array contains the following members:
+ * - `uid`, which is the UID of each remote speaker
+ * - `spectrumData`, which reports the audio spectrum of each remote speaker.
+ * @param spectrumNumber The array length of the spectrums.
+ * - true: Processed.
+ * - false: Not processed.
+ */
+ virtual bool onRemoteAudioSpectrum(const UserAudioSpectrumInfo * spectrums, unsigned int spectrumNumber) = 0;
+};
+
+/**
+ * The IVideoEncodedFrameObserver class.
+ */
+class IVideoEncodedFrameObserver {
+ public:
+ /**
+ * Occurs each time the SDK receives an encoded video image.
+ * @param uid The user id of remote user.
+ * @param imageBuffer The pointer to the video image buffer.
+ * @param length The data length of the video image.
+ * @param videoEncodedFrameInfo The information of the encoded video frame: EncodedVideoFrameInfo.
+ * @return Determines whether to accept encoded video image.
+ * - true: Accept.
+ * - false: Do not accept.
+ */
+ virtual bool onEncodedVideoFrameReceived(rtc::uid_t uid, const uint8_t* imageBuffer, size_t length,
+ const rtc::EncodedVideoFrameInfo& videoEncodedFrameInfo) = 0;
+
+ virtual ~IVideoEncodedFrameObserver() {}
+};
+
+/**
+ * The IVideoFrameObserver class.
+ */
+class IVideoFrameObserver {
+ public:
+ typedef media::base::VideoFrame VideoFrame;
+ /**
+ * The process mode of the video frame:
+ */
+ enum VIDEO_FRAME_PROCESS_MODE {
+ /**
+ * Read-only mode.
+ *
+ * In this mode, you do not modify the video frame. The video frame observer is a renderer.
+ */
+ PROCESS_MODE_READ_ONLY, // Observer works as a pure renderer and will not modify the original frame.
+ /**
+ * Read and write mode.
+ *
+ * In this mode, you modify the video frame. The video frame observer is a video filter.
+ */
+ PROCESS_MODE_READ_WRITE, // Observer works as a filter that will process the video frame and affect the following frame processing in SDK.
+ };
+
+ public:
+ virtual ~IVideoFrameObserver() {}
+
+ /**
+ * Occurs each time the SDK receives a video frame captured by the local camera.
+ *
+ * After you successfully register the video frame observer, the SDK triggers this callback each time
+ * a video frame is received. In this callback, you can get the video data captured by the local
+ * camera. You can then pre-process the data according to your scenarios.
+ *
+ * After pre-processing, you can send the processed video data back to the SDK by setting the
+ * `videoFrame` parameter in this callback.
+ *
+ * @note
+ * - If you get the video data in RGBA color encoding format, Agora does not support using this callback to send the processed data in RGBA color encoding format back to the SDK.
+ * - The video data that this callback gets has not been pre-processed, such as watermarking, cropping content, rotating, or image enhancement.
+ *
+ * @param videoFrame A pointer to the video frame: VideoFrame
+ * @param type source type of video frame. See #VIDEO_SOURCE_TYPE.
+ * @return Determines whether to ignore the current video frame if the pre-processing fails:
+ * - true: Do not ignore.
+ * - false: Ignore, in which case this method does not sent the current video frame to the SDK.
+ */
+ virtual bool onCaptureVideoFrame(agora::rtc::VIDEO_SOURCE_TYPE type, VideoFrame& videoFrame) = 0;
+
+ /**
+ * Occurs each time the SDK receives a video frame before encoding.
+ *
+ * After you successfully register the video frame observer, the SDK triggers this callback each time
+ * when it receives a video frame. In this callback, you can get the video data before encoding. You can then
+ * process the data according to your particular scenarios.
+ *
+ * After processing, you can send the processed video data back to the SDK by setting the
+ * `videoFrame` parameter in this callback.
+ *
+ * @note
+ * - To get the video data captured from the second screen before encoding, you need to set (1 << 2) as a frame position through `getObservedFramePosition`.
+ * - The video data that this callback gets has been pre-processed, such as watermarking, cropping content, rotating, or image enhancement.
+ * - This callback does not support sending processed RGBA video data back to the SDK.
+ *
+ * @param videoFrame A pointer to the video frame: VideoFrame
+ * @param type source type of video frame. See #VIDEO_SOURCE_TYPE.
+ * @return Determines whether to ignore the current video frame if the pre-processing fails:
+ * - true: Do not ignore.
+ * - false: Ignore, in which case this method does not sent the current video frame to the SDK.
+ */
+ virtual bool onPreEncodeVideoFrame(agora::rtc::VIDEO_SOURCE_TYPE type, VideoFrame& videoFrame) = 0;
+
+ /**
+ * Occurs each time the SDK receives a video frame decoded by the MediaPlayer.
+ *
+ * After you successfully register the video frame observer, the SDK triggers this callback each
+ * time a video frame is decoded. In this callback, you can get the video data decoded by the
+ * MediaPlayer. You can then pre-process the data according to your scenarios.
+ *
+ * After pre-processing, you can send the processed video data back to the SDK by setting the
+ * `videoFrame` parameter in this callback.
+ *
+ * @note
+ * If the returned agora::media::base::VIDEO_PIXEL_DEFAULT format is specified by getVideoFormatPreference,
+ * the video frame you get through onMediaPlayerVideoFrame is in agora::media::base::VIDEO_PIXEL_I420 format.
+ *
+ * @param videoFrame A pointer to the video frame: VideoFrame
+ * @param mediaPlayerId ID of the mediaPlayer.
+ * @return Determines whether to ignore the current video frame if the pre-processing fails:
+ * - true: Do not ignore.
+ * - false: Ignore, in which case this method does not sent the current video frame to the SDK.
+ */
+ virtual bool onMediaPlayerVideoFrame(VideoFrame& videoFrame, int mediaPlayerId) = 0;
+
+ /**
+ * Occurs each time the SDK receives a video frame sent by the remote user.
+ *
+ * After you successfully register the video frame observer, the SDK triggers this callback each time a
+ * video frame is received. In this callback, you can get the video data sent by the remote user. You
+ * can then post-process the data according to your scenarios.
+ *
+ * After post-processing, you can send the processed data back to the SDK by setting the `videoFrame`
+ * parameter in this callback.
+ *
+ * @note This callback does not support sending processed RGBA video data back to the SDK.
+ *
+ * @param channelId The channel name
+ * @param remoteUid ID of the remote user who sends the current video frame.
+ * @param videoFrame A pointer to the video frame: VideoFrame
+ * @return Determines whether to ignore the current video frame if the post-processing fails:
+ * - true: Do not ignore.
+ * - false: Ignore, in which case this method does not sent the current video frame to the SDK.
+ */
+ virtual bool onRenderVideoFrame(const char* channelId, rtc::uid_t remoteUid, VideoFrame& videoFrame) = 0;
+
+ virtual bool onTranscodedVideoFrame(VideoFrame& videoFrame) = 0;
+
+ /**
+ * Occurs each time the SDK receives a video frame and prompts you to set the process mode of the video frame.
+ *
+ * After you successfully register the video frame observer, the SDK triggers this callback each time it receives
+ * a video frame. You need to set your preferred process mode in the return value of this callback.
+ * @return VIDEO_FRAME_PROCESS_MODE.
+ */
+ virtual VIDEO_FRAME_PROCESS_MODE getVideoFrameProcessMode() {
+ return PROCESS_MODE_READ_ONLY;
+ }
+
+ /**
+ * Sets the format of the raw video data output by the SDK.
+ *
+ * If you want to get raw video data in a color encoding format other than YUV 420, register this callback when
+ * calling `registerVideoFrameObserver`. After you successfully register the video frame observer, the SDK triggers
+ * this callback each time it receives a video frame. You need to set your preferred video data in the return value
+ * of this callback.
+ *
+ * @note If you want the video captured by the sender to be the original format, set the original video data format
+ * to VIDEO_PIXEL_DEFAULT in the return value. On different platforms, the original video pixel format is also
+ * different, for the actual video pixel format, see `VideoFrame`.
+ *
+ * @return Sets the video format. See VIDEO_PIXEL_FORMAT.
+ */
+ virtual base::VIDEO_PIXEL_FORMAT getVideoFormatPreference() { return base::VIDEO_PIXEL_DEFAULT; }
+
+ /**
+ * Occurs each time the SDK receives a video frame, and prompts you whether to rotate the captured video.
+ *
+ * If you want to rotate the captured video according to the rotation member in the `VideoFrame` class, register this
+ * callback by calling `registerVideoFrameObserver`. After you successfully register the video frame observer, the
+ * SDK triggers this callback each time it receives a video frame. You need to set whether to rotate the video frame
+ * in the return value of this callback.
+ *
+ * @note This function only supports video data in RGBA or YUV420.
+ *
+ * @return Determines whether to rotate.
+ * - `true`: Rotate the captured video.
+ * - `false`: (Default) Do not rotate the captured video.
+ */
+ virtual bool getRotationApplied() { return false; }
+
+ /**
+ * Occurs each time the SDK receives a video frame and prompts you whether or not to mirror the captured video.
+ *
+ * If the video data you want to obtain is a mirror image of the original video, you need to register this callback
+ * when calling `registerVideoFrameObserver`. After you successfully register the video frame observer, the SDK
+ * triggers this callback each time it receives a video frame. You need to set whether or not to mirror the video
+ * frame in the return value of this callback.
+ *
+ * @note This function only supports video data in RGBA and YUV420 formats.
+ *
+ * @return Determines whether to mirror.
+ * - `true`: Mirror the captured video.
+ * - `false`: (Default) Do not mirror the captured video.
+ */
+ virtual bool getMirrorApplied() { return false; }
+
+ /**
+ * Sets the frame position for the video observer.
+ *
+ * After you successfully register the video observer, the SDK triggers this callback each time it receives
+ * a video frame. You can determine which position to observe by setting the return value. The SDK provides
+ * 3 positions for observer. Each position corresponds to a callback function:
+ *
+ * POSITION_POST_CAPTURER(1 << 0): The position after capturing the video data, which corresponds to the onCaptureVideoFrame callback.
+ * POSITION_PRE_RENDERER(1 << 1): The position before receiving the remote video data, which corresponds to the onRenderVideoFrame callback.
+ * POSITION_PRE_ENCODER(1 << 2): The position before encoding the video data, which corresponds to the onPreEncodeVideoFrame callback.
+ *
+ * To observe multiple frame positions, use '|' (the OR operator).
+ * This callback observes POSITION_POST_CAPTURER(1 << 0) and POSITION_PRE_RENDERER(1 << 1) by default.
+ * To conserve the system consumption, you can reduce the number of frame positions that you want to observe.
+ *
+ * @return A bit mask that controls the frame position of the video observer: VIDEO_OBSERVER_POSITION.
+ */
+ virtual uint32_t getObservedFramePosition() {
+ return base::POSITION_POST_CAPTURER | base::POSITION_PRE_RENDERER;
+ }
+
+ /**
+ * Indicate if the observer is for internal use.
+ * Note: Never override this function
+ * @return
+ * - true: the observer is for external use
+ * - false: the observer is for internal use
+ */
+ virtual bool isExternal() { return true; }
+};
+
+/**
+ * The external video source type.
+ */
+enum EXTERNAL_VIDEO_SOURCE_TYPE {
+ /**
+ * 0: non-encoded video frame.
+ */
+ VIDEO_FRAME = 0,
+ /**
+ * 1: encoded video frame.
+ */
+ ENCODED_VIDEO_FRAME,
+};
+
+/**
+ * The format of the recording file.
+ *
+ * @since v3.5.2
+ */
+enum MediaRecorderContainerFormat {
+ /**
+ * 1: (Default) MP4.
+ */
+ FORMAT_MP4 = 1,
+};
+/**
+ * The recording content.
+ *
+ * @since v3.5.2
+ */
+enum MediaRecorderStreamType {
+ /**
+ * Only audio.
+ */
+ STREAM_TYPE_AUDIO = 0x01,
+ /**
+ * Only video.
+ */
+ STREAM_TYPE_VIDEO = 0x02,
+ /**
+ * (Default) Audio and video.
+ */
+ STREAM_TYPE_BOTH = STREAM_TYPE_AUDIO | STREAM_TYPE_VIDEO,
+};
+/**
+ * The current recording state.
+ *
+ * @since v3.5.2
+ */
+enum RecorderState {
+ /**
+ * -1: An error occurs during the recording. See RecorderErrorCode for the reason.
+ */
+ RECORDER_STATE_ERROR = -1,
+ /**
+ * 2: The audio and video recording is started.
+ */
+ RECORDER_STATE_START = 2,
+ /**
+ * 3: The audio and video recording is stopped.
+ */
+ RECORDER_STATE_STOP = 3,
+};
+/**
+ * The reason for the state change
+ *
+ * @since v3.5.2
+ */
+enum RecorderErrorCode {
+ /**
+ * 0: No error occurs.
+ */
+ RECORDER_ERROR_NONE = 0,
+ /**
+ * 1: The SDK fails to write the recorded data to a file.
+ */
+ RECORDER_ERROR_WRITE_FAILED = 1,
+ /**
+ * 2: The SDK does not detect audio and video streams to be recorded, or audio and video streams are interrupted for more than five seconds during recording.
+ */
+ RECORDER_ERROR_NO_STREAM = 2,
+ /**
+ * 3: The recording duration exceeds the upper limit.
+ */
+ RECORDER_ERROR_OVER_MAX_DURATION = 3,
+ /**
+ * 4: The recording configuration changes.
+ */
+ RECORDER_ERROR_CONFIG_CHANGED = 4,
+};
+/**
+ * Configurations for the local audio and video recording.
+ *
+ * @since v3.5.2
+ */
+struct MediaRecorderConfiguration {
+ /**
+ * The absolute path (including the filename extensions) of the recording file.
+ * For example, `C:\Users\\AppData\Local\Agora\\example.mp4` on Windows,
+ * `/App Sandbox/Library/Caches/example.mp4` on iOS, `/Library/Logs/example.mp4` on macOS, and
+ * `/storage/emulated/0/Android/data//files/example.mp4` on Android.
+ *
+ * @note Ensure that the specified path exists and is writable.
+ */
+ const char* storagePath;
+ /**
+ * The format of the recording file. See \ref agora::rtc::MediaRecorderContainerFormat "MediaRecorderContainerFormat".
+ */
+ MediaRecorderContainerFormat containerFormat;
+ /**
+ * The recording content. See \ref agora::rtc::MediaRecorderStreamType "MediaRecorderStreamType".
+ */
+ MediaRecorderStreamType streamType;
+ /**
+ * The maximum recording duration, in milliseconds. The default value is 120000.
+ */
+ int maxDurationMs;
+ /**
+ * The interval (ms) of updating the recording information. The value range is
+ * [1000,10000]. Based on the set value of `recorderInfoUpdateInterval`, the
+ * SDK triggers the \ref IMediaRecorderObserver::onRecorderInfoUpdated "onRecorderInfoUpdated"
+ * callback to report the updated recording information.
+ */
+ int recorderInfoUpdateInterval;
+
+ MediaRecorderConfiguration() : storagePath(NULL), containerFormat(FORMAT_MP4), streamType(STREAM_TYPE_BOTH), maxDurationMs(120000), recorderInfoUpdateInterval(0) {}
+ MediaRecorderConfiguration(const char* path, MediaRecorderContainerFormat format, MediaRecorderStreamType type, int duration, int interval) : storagePath(path), containerFormat(format), streamType(type), maxDurationMs(duration), recorderInfoUpdateInterval(interval) {}
+};
+/**
+ * Information for the recording file.
+ *
+ * @since v3.5.2
+ */
+struct RecorderInfo {
+ /**
+ * The absolute path of the recording file.
+ */
+ const char* fileName;
+ /**
+ * The recording duration, in milliseconds.
+ */
+ unsigned int durationMs;
+ /**
+ * The size in bytes of the recording file.
+ */
+ unsigned int fileSize;
+
+ RecorderInfo() : fileName(NULL), durationMs(0), fileSize(0) {}
+ RecorderInfo(const char* name, unsigned int dur, unsigned int size) : fileName(name), durationMs(dur), fileSize(size) {}
+};
+
+
+class IMediaRecorderObserver {
+ public:
+ /**
+ * Occurs when the recording state changes.
+ *
+ * @since v3.5.2
+ *
+ * When the local audio and video recording state changes, the SDK triggers this callback to report the current
+ * recording state and the reason for the change.
+ *
+ * @param state The current recording state. See \ref agora::rtc::RecorderState "RecorderState".
+ * @param error The reason for the state change. See \ref agora::rtc::RecorderErrorCode "RecorderErrorCode".
+ */
+ virtual void onRecorderStateChanged(RecorderState state, RecorderErrorCode error) = 0;
+ /**
+ * Occurs when the recording information is updated.
+ *
+ * @since v3.5.2
+ *
+ * After you successfully register this callback and enable the local audio and video recording, the SDK periodically triggers
+ * the `onRecorderInfoUpdated` callback based on the set value of `recorderInfoUpdateInterval`. This callback reports the
+ * filename, duration, and size of the current recording file.
+ *
+ * @param info Information for the recording file. See RecorderInfo.
+ *
+ */
+ virtual void onRecorderInfoUpdated(const RecorderInfo& info) = 0;
+ virtual ~IMediaRecorderObserver() {}
+};
+} // namespace media
+} // namespace agora
diff --git a/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraMediaFilterEventDelegate.h b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraMediaFilterEventDelegate.h
new file mode 100644
index 0000000..5e2a6d6
--- /dev/null
+++ b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraMediaFilterEventDelegate.h
@@ -0,0 +1,67 @@
+//
+// AgoraMediaFilterEventDelegate.h
+// Agora SDK
+//
+// Created by LLF on 2020-9-21.
+// Copyright (c) 2020 Agora. All rights reserved.
+//
+
+#import
+
+@interface AgoraExtensionContext : NSObject
+/** Whether uid is valid.
+ */
+@property (assign, nonatomic) BOOL isValid;
+/** Default 0 when "isValid is NO
+ * Local user is 0 and remote user great than 0 when "isValid" is YES
+ */
+@property (assign, nonatomic) NSUInteger uid;
+@property (copy, nonatomic) NSString * _Nullable providerName;
+@property (copy, nonatomic) NSString * _Nullable extensionName;
+
+@end
+
+@protocol AgoraMediaFilterEventDelegate
+@optional
+/* Meida filter(audio filter or video filter) event callback
+ */
+- (void)onEvent:(NSString * __nullable)provider
+ extension:(NSString * __nullable)extension
+ key:(NSString * __nullable)key
+ value:(NSString * __nullable)value NS_SWIFT_NAME(onEvent(_:extension:key:value:)) __deprecated_msg("override needExtensionContext, use onEventWithContext instead");
+
+- (void)onExtensionStopped:(NSString * __nullable)provider
+ extension:(NSString * __nullable)extension NS_SWIFT_NAME(onExtensionStopped(_:extension:))
+ __deprecated_msg("override needExtensionContext, use onExtensionStoppedWithContext instead");
+
+- (void)onExtensionStarted:(NSString * __nullable)provider
+ extension:(NSString * __nullable)extension NS_SWIFT_NAME(onExtensionStarted(_:extension:))
+ __deprecated_msg("override needExtensionContext, use onExtensionStartedWithContext instead");
+
+- (void)onExtensionError:(NSString * __nullable)provider
+ extension:(NSString * __nullable)extension
+ error:(int)error
+ message:(NSString * __nullable)message NS_SWIFT_NAME(onExtensionError(_:extension:error:message:))
+ __deprecated_msg("override needExtensionContext, use onExtensionErrorWithContext instead");
+
+/** Whether need ExtensionContext, default NO if doesn't impl
+ *
+ * recommend override for YES
+ * return NO, then callback interface with onEvent、onExtensionStarted、onExtensionStopped、onExtensionError
+ * return YES, then callback interface conterpart with *WithContext interface
+ */
+- (BOOL)needExtensionContext NS_SWIFT_NAME(needExtensionContext());//
+
+- (void)onEventWithContext:(AgoraExtensionContext * __nonnull)context
+ key:(NSString * __nullable)key
+ value:(NSString * __nullable)value NS_SWIFT_NAME(onEventWithContext(_:key:value:));
+
+- (void)onExtensionStartedWithContext:(AgoraExtensionContext * __nonnull)context NS_SWIFT_NAME(onExtensionStartedWithContext(_:));
+
+- (void)onExtensionStoppedWithContext:(AgoraExtensionContext * __nonnull)context NS_SWIFT_NAME(onExtensionStoppedWithContext(_:));
+
+- (void)onExtensionErrorWithContext:(AgoraExtensionContext * __nonnull)context
+ error:(int)error
+ message:(NSString * __nullable)message NS_SWIFT_NAME(onExtensionErrorWithContext(_:error:message:));
+
+@end
diff --git a/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraMediaPlayerTypes.h b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraMediaPlayerTypes.h
new file mode 100644
index 0000000..b446bf0
--- /dev/null
+++ b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraMediaPlayerTypes.h
@@ -0,0 +1,474 @@
+//
+// Agora Engine SDK
+//
+// Created by Sting Feng in 2020-05.
+// Copyright (c) 2017 Agora.io. All rights reserved.
+
+#pragma once // NOLINT(build/header_guard)
+
+#include
+#include
+
+#include "AgoraOptional.h"
+
+/**
+ * set analyze duration for real time stream
+ * @example "setPlayerOption(KEY_PLAYER_REAL_TIME_STREAM_ANALYZE_DURATION,1000000)"
+ */
+#define KEY_PLAYER_REAL_TIME_STREAM_ANALYZE_DURATION "analyze_duration"
+
+/**
+ * make the player to enable audio or not
+ * @example "setPlayerOption(KEY_PLAYER_ENABLE_AUDIO,0)"
+ */
+#define KEY_PLAYER_ENABLE_AUDIO "enable_audio"
+
+/**
+ * make the player to enable video or not
+ * @example "setPlayerOption(KEY_PLAYER_ENABLE_VIDEO,0)"
+ */
+#define KEY_PLAYER_ENABLE_VIDEO "enable_video"
+
+/**
+ * set the player enable to search metadata
+ * @example "setPlayerOption(KEY_PLAYER_DISABLE_SEARCH_METADATA,0)"
+ */
+#define KEY_PLAYER_ENABLE_SEARCH_METADATA "enable_search_metadata"
+
+/**
+ * set the player sei filter type
+ * @example "setPlayerOption(KEY_PLAYER_SEI_FILTER_TYPE,"5")"
+ */
+#define KEY_PLAYER_SEI_FILTER_TYPE "set_sei_filter_type"
+
+namespace agora {
+
+namespace media {
+
+namespace base {
+static const uint8_t kMaxCharBufferLength = 50;
+/**
+ * @brief The playback state.
+ *
+ */
+enum MEDIA_PLAYER_STATE {
+ /** Default state.
+ */
+ PLAYER_STATE_IDLE = 0,
+ /** Opening the media file.
+ */
+ PLAYER_STATE_OPENING,
+ /** The media file is opened successfully.
+ */
+ PLAYER_STATE_OPEN_COMPLETED,
+ /** Playing the media file.
+ */
+ PLAYER_STATE_PLAYING,
+ /** The playback is paused.
+ */
+ PLAYER_STATE_PAUSED,
+ /** The playback is completed.
+ */
+ PLAYER_STATE_PLAYBACK_COMPLETED,
+ /** All loops are completed.
+ */
+ PLAYER_STATE_PLAYBACK_ALL_LOOPS_COMPLETED,
+ /** The playback is stopped.
+ */
+ PLAYER_STATE_STOPPED,
+ /** Player pausing (internal)
+ */
+ PLAYER_STATE_PAUSING_INTERNAL = 50,
+ /** Player stopping (internal)
+ */
+ PLAYER_STATE_STOPPING_INTERNAL,
+ /** Player seeking state (internal)
+ */
+ PLAYER_STATE_SEEKING_INTERNAL,
+ /** Player getting state (internal)
+ */
+ PLAYER_STATE_GETTING_INTERNAL,
+ /** None state for state machine (internal)
+ */
+ PLAYER_STATE_NONE_INTERNAL,
+ /** Do nothing state for state machine (internal)
+ */
+ PLAYER_STATE_DO_NOTHING_INTERNAL,
+ /** Player set track state (internal)
+ */
+ PLAYER_STATE_SET_TRACK_INTERNAL,
+ /** The playback fails.
+ */
+ PLAYER_STATE_FAILED = 100,
+};
+/**
+ * @brief Player error code
+ *
+ */
+enum MEDIA_PLAYER_ERROR {
+ /** No error.
+ */
+ PLAYER_ERROR_NONE = 0,
+ /** The parameter is invalid.
+ */
+ PLAYER_ERROR_INVALID_ARGUMENTS = -1,
+ /** Internel error.
+ */
+ PLAYER_ERROR_INTERNAL = -2,
+ /** No resource.
+ */
+ PLAYER_ERROR_NO_RESOURCE = -3,
+ /** Invalid media source.
+ */
+ PLAYER_ERROR_INVALID_MEDIA_SOURCE = -4,
+ /** The type of the media stream is unknown.
+ */
+ PLAYER_ERROR_UNKNOWN_STREAM_TYPE = -5,
+ /** The object is not initialized.
+ */
+ PLAYER_ERROR_OBJ_NOT_INITIALIZED = -6,
+ /** The codec is not supported.
+ */
+ PLAYER_ERROR_CODEC_NOT_SUPPORTED = -7,
+ /** Invalid renderer.
+ */
+ PLAYER_ERROR_VIDEO_RENDER_FAILED = -8,
+ /** An error occurs in the internal state of the player.
+ */
+ PLAYER_ERROR_INVALID_STATE = -9,
+ /** The URL of the media file cannot be found.
+ */
+ PLAYER_ERROR_URL_NOT_FOUND = -10,
+ /** Invalid connection between the player and the Agora server.
+ */
+ PLAYER_ERROR_INVALID_CONNECTION_STATE = -11,
+ /** The playback buffer is insufficient.
+ */
+ PLAYER_ERROR_SRC_BUFFER_UNDERFLOW = -12,
+ /** The audio mixing file playback is interrupted.
+ */
+ PLAYER_ERROR_INTERRUPTED = -13,
+ /** The SDK does not support this function.
+ */
+ PLAYER_ERROR_NOT_SUPPORTED = -14,
+ /** The token has expired.
+ */
+ PLAYER_ERROR_TOKEN_EXPIRED = -15,
+ /** The ip has expired.
+ */
+ PLAYER_ERROR_IP_EXPIRED = -16,
+ /** An unknown error occurs.
+ */
+ PLAYER_ERROR_UNKNOWN = -17,
+};
+
+/**
+ * @brief The type of the media stream.
+ *
+ */
+enum MEDIA_STREAM_TYPE {
+ /** The type is unknown.
+ */
+ STREAM_TYPE_UNKNOWN = 0,
+ /** The video stream.
+ */
+ STREAM_TYPE_VIDEO = 1,
+ /** The audio stream.
+ */
+ STREAM_TYPE_AUDIO = 2,
+ /** The subtitle stream.
+ */
+ STREAM_TYPE_SUBTITLE = 3,
+};
+
+/**
+ * @brief The playback event.
+ *
+ */
+enum MEDIA_PLAYER_EVENT {
+ /** The player begins to seek to the new playback position.
+ */
+ PLAYER_EVENT_SEEK_BEGIN = 0,
+ /** The seek operation completes.
+ */
+ PLAYER_EVENT_SEEK_COMPLETE = 1,
+ /** An error occurs during the seek operation.
+ */
+ PLAYER_EVENT_SEEK_ERROR = 2,
+ /** The player changes the audio track for playback.
+ */
+ PLAYER_EVENT_AUDIO_TRACK_CHANGED = 5,
+ /** player buffer low
+ */
+ PLAYER_EVENT_BUFFER_LOW = 6,
+ /** player buffer recover
+ */
+ PLAYER_EVENT_BUFFER_RECOVER = 7,
+ /** The video or audio is interrupted
+ */
+ PLAYER_EVENT_FREEZE_START = 8,
+ /** Interrupt at the end of the video or audio
+ */
+ PLAYER_EVENT_FREEZE_STOP = 9,
+ /** switch source begin
+ */
+ PLAYER_EVENT_SWITCH_BEGIN = 10,
+ /** switch source complete
+ */
+ PLAYER_EVENT_SWITCH_COMPLETE = 11,
+ /** switch source error
+ */
+ PLAYER_EVENT_SWITCH_ERROR = 12,
+ /** An application can render the video to less than a second
+ */
+ PLAYER_EVENT_FIRST_DISPLAYED = 13,
+ /** cache resources exceed the maximum file count
+ */
+ PLAYER_EVENT_REACH_CACHE_FILE_MAX_COUNT = 14,
+ /** cache resources exceed the maximum file size
+ */
+ PLAYER_EVENT_REACH_CACHE_FILE_MAX_SIZE = 15,
+ /** Triggered when a retry is required to open the media
+ */
+ PLAYER_EVENT_TRY_OPEN_START = 16,
+ /** Triggered when the retry to open the media is successful
+ */
+ PLAYER_EVENT_TRY_OPEN_SUCCEED = 17,
+ /** Triggered when retrying to open media fails
+ */
+ PLAYER_EVENT_TRY_OPEN_FAILED = 18,
+};
+
+/**
+ * @brief The play preload another source event.
+ *
+ */
+enum PLAYER_PRELOAD_EVENT {
+ /** preload source begin
+ */
+ PLAYER_PRELOAD_EVENT_BEGIN = 0,
+ /** preload source complete
+ */
+ PLAYER_PRELOAD_EVENT_COMPLETE = 1,
+ /** preload source error
+ */
+ PLAYER_PRELOAD_EVENT_ERROR = 2,
+};
+
+/**
+ * @brief The information of the media stream object.
+ *
+ */
+struct PlayerStreamInfo {
+ /** The index of the media stream. */
+ int streamIndex;
+
+ /** The type of the media stream. See {@link MEDIA_STREAM_TYPE}. */
+ MEDIA_STREAM_TYPE streamType;
+
+ /** The codec of the media stream. */
+ char codecName[kMaxCharBufferLength];
+
+ /** The language of the media stream. */
+ char language[kMaxCharBufferLength];
+
+ /** The frame rate (fps) if the stream is video. */
+ int videoFrameRate;
+
+ /** The video bitrate (bps) if the stream is video. */
+ int videoBitRate;
+
+ /** The video width (pixel) if the stream is video. */
+ int videoWidth;
+
+ /** The video height (pixel) if the stream is video. */
+ int videoHeight;
+
+ /** The rotation angle if the steam is video. */
+ int videoRotation;
+
+ /** The sample rate if the stream is audio. */
+ int audioSampleRate;
+
+ /** The number of audio channels if the stream is audio. */
+ int audioChannels;
+
+ /** The number of bits per sample if the stream is audio. */
+ int audioBitsPerSample;
+
+ /** The total duration (millisecond) of the media stream. */
+ int64_t duration;
+
+ PlayerStreamInfo() : streamIndex(0),
+ streamType(STREAM_TYPE_UNKNOWN),
+ videoFrameRate(0),
+ videoBitRate(0),
+ videoWidth(0),
+ videoHeight(0),
+ videoRotation(0),
+ audioSampleRate(0),
+ audioChannels(0),
+ audioBitsPerSample(0),
+ duration(0) {
+ memset(codecName, 0, sizeof(codecName));
+ memset(language, 0, sizeof(language));
+ }
+};
+
+/**
+ * @brief The information of the media stream object.
+ *
+ */
+struct SrcInfo {
+ /** The bitrate of the media stream. The unit of the number is kbps.
+ *
+ */
+ int bitrateInKbps;
+
+ /** The name of the media stream.
+ *
+ */
+ const char* name;
+
+};
+
+/**
+ * @brief The type of the media metadata.
+ *
+ */
+enum MEDIA_PLAYER_METADATA_TYPE {
+ /** The type is unknown.
+ */
+ PLAYER_METADATA_TYPE_UNKNOWN = 0,
+ /** The type is SEI.
+ */
+ PLAYER_METADATA_TYPE_SEI = 1,
+};
+
+struct CacheStatistics {
+ /** total data size of uri
+ */
+ int64_t fileSize;
+ /** data of uri has cached
+ */
+ int64_t cacheSize;
+ /** data of uri has downloaded
+ */
+ int64_t downloadSize;
+};
+
+struct PlayerUpdatedInfo {
+ /** playerId has value when user trigger interface of opening
+ */
+ Optional playerId;
+
+ /** deviceId has value when user trigger interface of opening
+ */
+ Optional deviceId;
+
+ /** cacheStatistics exist if you enable cache, triggered 1s at a time after openning url
+ */
+ Optional cacheStatistics;
+};
+
+/**
+ * The custom data source provides a data stream input callback, and the player will continue to call back this interface, requesting the user to fill in the data that needs to be played.
+ */
+class IMediaPlayerCustomDataProvider {
+public:
+
+ /**
+ * @brief The player requests to read the data callback, you need to fill the specified length of data into the buffer
+ * @param buffer the buffer pointer that you need to fill data.
+ * @param bufferSize the bufferSize need to fill of the buffer pointer.
+ * @return you need return offset value if succeed. return 0 if failed.
+ */
+ virtual int onReadData(unsigned char *buffer, int bufferSize) = 0;
+
+ /**
+ * @brief The Player seek event callback, you need to operate the corresponding stream seek operation, You can refer to the definition of lseek() at https://man7.org/linux/man-pages/man2/lseek.2.html
+ * @param offset the value of seek offset.
+ * @param whence the postion of start seeking, the directive whence as follows:
+ * 0 - SEEK_SET : The file offset is set to offset bytes.
+ * 1 - SEEK_CUR : The file offset is set to its current location plus offset bytes.
+ * 2 - SEEK_END : The file offset is set to the size of the file plus offset bytes.
+ * 65536 - AVSEEK_SIZE : Optional. Passing this as the "whence" parameter to a seek function causes it to return the filesize without seeking anywhere.
+ * @return
+ * whence == 65536, return filesize if you need.
+ * whence >= 0 && whence < 3 , return offset value if succeed. return -1 if failed.
+ */
+ virtual int64_t onSeek(int64_t offset, int whence) = 0;
+
+ virtual ~IMediaPlayerCustomDataProvider() {}
+};
+
+struct MediaSource {
+ /**
+ * The URL of the media file that you want to play.
+ */
+ const char* url;
+ /**
+ * The URI of the media file
+ *
+ * When caching is enabled, if the url cannot distinguish the cache file name,
+ * the uri must be able to ensure that the cache file name corresponding to the url is unique.
+ */
+ const char* uri;
+ /**
+ * Set the starting position for playback, in ms.
+ */
+ int64_t startPos;
+ /**
+ * Determines whether to autoplay after opening a media resource.
+ * - true: (Default) Autoplay after opening a media resource.
+ * - false: Do not autoplay after opening a media resource.
+ */
+ bool autoPlay;
+ /**
+ * Determines whether to enable cache streaming to local files. If enable cached, the media player will
+ * use the url or uri as the cache index.
+ *
+ * @note
+ * The local cache function only supports on-demand video/audio streams and does not support live streams.
+ * Caching video and audio files based on the HLS protocol (m3u8) to your local device is not supported.
+ *
+ * - true: Enable cache.
+ * - false: (Default) Disable cache.
+ */
+ bool enableCache;
+ /**
+ * Determines whether to enable multi-track audio stream decoding.
+ * Then you can select multi audio track of the media file for playback or publish to channel
+ *
+ * @note
+ * If you use the selectMultiAudioTrack API, you must set enableMultiAudioTrack to true.
+ *
+ * - true: Enable MultiAudioTrack;.
+ * - false: (Default) Disable MultiAudioTrack;.
+ */
+ bool enableMultiAudioTrack;
+ /**
+ * Determines whether the opened media resource is a stream through the Agora Broadcast Streaming Network(CDN).
+ * - true: It is a stream through the Agora Broadcast Streaming Network.
+ * - false: (Default) It is not a stream through the Agora Broadcast Streaming Network.
+ */
+ Optional isAgoraSource;
+ /**
+ * Determines whether the opened media resource is a live stream. If is a live stream, it can speed up the opening of media resources.
+ * - true: It is a live stream.
+ * - false: (Default) It is not is a live stream.
+ */
+ Optional isLiveSource;
+ /**
+ * External custom data source object
+ */
+ IMediaPlayerCustomDataProvider* provider;
+
+ MediaSource() : url(NULL), uri(NULL), startPos(0), autoPlay(true), enableCache(false),
+ enableMultiAudioTrack(false), provider(NULL){
+ }
+};
+
+} // namespace base
+} // namespace media
+} // namespace agora
diff --git a/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraMusicContentCenter.h b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraMusicContentCenter.h
new file mode 100644
index 0000000..98c0156
--- /dev/null
+++ b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraMusicContentCenter.h
@@ -0,0 +1,485 @@
+//
+// AgoraMusicContentCenter.h
+// AgoraMusicContentCenter
+//
+// Created by dingyusong on 2022/6/1.
+// Copyright © 2022 Agora. All rights reserved.
+//
+
+#import
+#import "AgoraRtcEngineKit.h"
+/**
+ * The status of preload request
+ */
+typedef NS_ENUM(NSUInteger, AgoraMusicContentCenterPreloadStatus) {
+ /**
+ * 0: No error occurs and preload succeeds.
+ */
+ AgoraMusicContentCenterPreloadStatusOK = 0,
+
+ /**
+ * 1: A general error occurs.
+ */
+ AgoraMusicContentCenterPreloadStatusError = 1,
+
+ /**
+ * 2: The media file is preloading.
+ */
+ AgoraMusicContentCenterPreloadStatusPreloading = 2,
+
+ /**
+ * 3: The media file is removed.
+ */
+ AgoraMusicContentCenterPreloadStatusRemoveCache = 3,
+};
+
+/**
+ * the status of search or get top list request
+ */
+typedef NS_ENUM(NSUInteger, AgoraMusicContentCenterStatusCode) {
+ /**
+ * 0: No error occurs and request succeeds.
+ */
+ AgoraMusicContentCenterStatusCodeOK = 0,
+ /**
+ * 1: A general error occurs.
+ */
+ AgoraMusicContentCenterStatusCodeError = 1,
+ /**
+ * 2: The gateway error. There are several possible reasons:
+ * - Token is expired. Check if your token is expired.
+ * - Token is invalid. Check the type of token you passed in.
+ * - Network error. Check your network.
+ */
+ AgoraMusicContentCenterStatusCodeErrorGateway = 2,
+ /**
+ * 3: Permission and resource error. There are several possible reasons:
+ * - Your appid may not have the mcc permission. Please contact technical support
+ * - The resource may not exist. Please contact technical support
+ */
+ AgoraMusicContentCenterStatusCodeErrorPermissionAndResource = 3,
+ /**
+ * 4: Internal data parse error. Please contact technical support
+ */
+ AgoraMusicContentCenterStatusCodeErrorInternalDataParse = 4,
+ /**
+ * 5: Music loading error. Please contact technical support
+ */
+ AgoraMusicContentCenterStatusCodeErrorMusicLoading = 5,
+ /**
+ * 6: Music decryption error. Please contact technical support
+ */
+ AgoraMusicContentCenterStatusCodeErrorMusicDecryption = 6,
+ /**
+ * 7: Http internal error. suggest retry later.
+ */
+ AgoraMusicContentCenterStatusCodeErrorHttpInternalError = 7,
+};
+
+typedef NS_ENUM(NSUInteger, AgoraMusicCacheStatusType) {
+ /**
+ * 0: The media file is already cached.
+ */
+ AgoraMusicCacheStatusTypeCached = 0,
+
+ /**
+ * 1: The media file is being cached.
+ */
+ AgoraMusicCacheStatusTypeCaching = 1,
+};
+
+NS_ASSUME_NONNULL_BEGIN
+
+__attribute__((visibility("default"))) @interface AgoraMusicCacheInfo : NSObject
+/**
+ * The songCode of the music
+ */
+@property(nonatomic, assign) NSInteger songCode;
+
+/**
+ * The cache status of the music
+ */
+@property(nonatomic, assign) AgoraMusicCacheStatusType statusType;
+@end
+
+__attribute__((visibility("default"))) @interface AgoraMusicChartInfo : NSObject
+/**
+ * Name of the music chart
+ */
+@property (nonatomic, copy) NSString *chartName;
+/**
+ * Id of the music chart, which is used to get music list
+ */
+@property (nonatomic, assign) NSInteger identify;
+@end
+
+__attribute__((visibility("default"))) @interface AgoraMvProperty : NSObject
+/**
+ * The resolution of the mv
+ */
+@property (nonatomic, copy) NSString *resolution;
+/**
+ * The bandwidth of the mv
+ */
+@property (nonatomic, copy) NSString *bandwidth;
+@end
+
+__attribute__((visibility("default"))) @interface AgoraClimaxSegment : NSObject
+/**
+ * The start time of climax segment
+ */
+@property(nonatomic, assign) NSInteger startTimeMs;
+/**
+ * The end time of climax segment
+ */
+@property(nonatomic, assign) NSInteger endTimeMs;
+@end
+
+/**
+ * The music info
+ */
+__attribute__((visibility("default"))) @interface AgoraMusic : NSObject
+/**
+ * The songCode of music
+ */
+@property(nonatomic, assign) NSInteger songCode;
+/**
+ * The type of music
+ * 1, mp3 with instrumental accompaniment and original
+ * 2, mp3 only with instrumental accompaniment
+ * 3, mp3 only with original
+ * 4, mp4 with instrumental accompaniment and original
+ * 5, mv only
+ * 6, new type mp4 with instrumental accompaniment and original
+ * detail at document of music media center
+ */
+@property(nonatomic, assign) NSInteger type;
+/**
+ * The pitch type of music.
+ * 1, xml lyric has pitch
+ * 2, lyric has no pitch
+ */
+@property(nonatomic, assign) NSInteger pitchType;
+/**
+ * The name of music
+ */
+@property(nonatomic, copy) NSString* name;
+/**
+ * The singer of music
+ */
+@property(nonatomic, copy) NSString* singer;
+/**
+ * The poster url of music
+ */
+@property(nonatomic, copy) NSString* poster;
+
+/**
+ * The release time of music
+ */
+@property(nonatomic, copy) NSString* releaseTime;
+/**
+ * The duration (in seconds) of music
+ */
+@property(nonatomic, assign) NSInteger durationS;
+/**
+ * The lyric list of music
+ * 0, xml
+ * 1, lrc
+ */
+@property(nonatomic, strong) NSArray* lyricList;
+/**
+ * The mv property list of music
+ */
+@property(nonatomic, strong) NSArray* mvPropertyList;
+/**
+ * The climax segment list of music
+ */
+@property(nonatomic, strong) NSArray* climaxSegmentList;
+@end
+
+/**
+ * The music collection info
+ */
+__attribute__((visibility("default"))) @interface AgoraMusicCollection : NSObject
+/**
+ * This page contains how many AgoraMusic object
+ */
+@property(nonatomic, assign) NSInteger count;
+/**
+ * Total number of this search result or total number of the type music sources
+ */
+@property(nonatomic, assign) NSInteger total;
+/**
+ * This current page number
+ */
+@property(nonatomic, assign) NSInteger page;
+/**
+ * This request page size
+ */
+@property(nonatomic, assign) NSInteger pageSize;
+/**
+ * This music list of the request result
+ */
+@property(nonatomic, strong) NSArray* musicList;
+@end
+
+/**
+ * The request event delegate callback
+ */
+@protocol AgoraMusicContentCenterEventDelegate
+/**
+ * The music chart result callback; occurs when getMusicCharts method is called.
+ *
+ * @param requestId The request id is same as that returned by getMusicCharts.
+ * @param result The result of music chart collection
+ * @param errorCode The status of the request. See MusicContentCenterStatusCode
+ */
+- (void)onMusicChartsResult:(NSString *)requestId result:(NSArray *)result errorCode:(AgoraMusicContentCenterStatusCode)errorCode;
+
+/**
+ * Music collection, occurs when getMusicCollectionByMusicChartId or searchMusic method is called.
+ *
+ * @param requestId The request id is the same with that returned by getMusicCollectionByMusicChartId or searchMusic
+ * @param result The result of music collection
+ * @param errorCode The status of the request. See MusicContentCenterStatusCode
+ */
+- (void)onMusicCollectionResult:(NSString *)requestId result:(AgoraMusicCollection *)result errorCode:(AgoraMusicContentCenterStatusCode)errorCode;
+
+/**
+ * Lyric url callback of getLyric, occurs when getLyric is called
+ *
+ * @param requestId The request id is same as that returned by getLyric
+ * @param songCode Song code
+ * @param lyricUrl The lyric url of this music
+ * @param errorCode The status of the request. See MusicContentCenterStatusCode
+ */
+- (void)onLyricResult:(NSString*)requestId songCode:(NSInteger)songCode lyricUrl:(NSString* _Nullable)lyricUrl errorCode:(AgoraMusicContentCenterStatusCode)errorCode;
+
+/**
+ * Simple info callback of getSongSimpleInfo, occurs when getSongSimpleInfo is called
+ *
+ * @param requestId The request id is same as that returned by getSongSimpleInfo.
+ * @param songCode Song code
+ * @param simpleinfo The metadata of the music.
+ * @param errorCode The status of the request. See MusicContentCenterStatusCode
+ */
+- (void)onSongSimpleInfoResult:(NSString*)requestId songCode:(NSInteger)songCode simpleInfo:(NSString* _Nullable)simpleInfo errorCode:(AgoraMusicContentCenterStatusCode)errorCode;
+
+/**
+ * Preload process callback, occurs when preload is called
+ *
+ * @param requestId The request id is same as that returned by preload.
+ * @param songCode Song code
+ * @param percent Preload progress (0 ~ 100)
+ * @param lyricUrl The lyric url of this music
+ * @param status Preload status; see PreloadStatusCode.
+ * @param errorCode The status of the request. See MusicContentCenterStatusCode
+ */
+- (void)onPreLoadEvent:(NSString*)requestId songCode:(NSInteger)songCode percent:(NSInteger)percent lyricUrl:(NSString * _Nullable)lyricUrl status:(AgoraMusicContentCenterPreloadStatus)status errorCode:(AgoraMusicContentCenterStatusCode)errorCode;
+@end
+
+
+@class AgoraRtcEngineKit;
+__attribute__((visibility("default"))) @interface AgoraMusicContentCenterConfig : NSObject
+@property(assign, nonatomic) AgoraRtcEngineKit* _Nullable rtcEngine;
+/**
+ * The app ID of the project that has enabled the music content center
+ */
+@property (nonatomic, copy) NSString *appId;
+/**
+ * music content center need token to connect with server
+ */
+@property (nonatomic, copy) NSString *token;
+/**
+ * The user ID when using music content center. It can be different from that of the rtc product.
+ */
+@property (nonatomic, assign) NSInteger mccUid;
+/**
+ * The max number which the music content center caches cannot exceed 50.
+ */
+@property (nonatomic, assign) NSUInteger maxCacheSize;
+/**
+ * The mccdomain, used to control the domain name of music contenter center,usually developer do not need to set it.Only under Tech supporter's help, can set the value
+ */
+@property(nonatomic, copy) NSString* mccDomain;
+/**
+ * Event handler to get callback result.
+ */
+@property(nonatomic, weak) id eventDelegate;
+@end
+
+@protocol AgoraMusicPlayerProtocol
+/**
+ * Open a media file with specified parameters.
+ *
+ * @param songCode The identifier of the media file that you want to play.
+ * @param startPos The playback position (ms) of the music file.
+ * @return
+ * - 0: Success.
+ * - < 0: Failure.
+ */
+- (NSInteger)openMediaWithSongCode:(NSInteger)songCode startPos:(NSInteger)startPos NS_SWIFT_NAME(openMedia(songCode:startPos:));
+@end
+
+
+__attribute__((visibility("default"))) @interface AgoraMusicContentCenter : NSObject
+
+/**
+ * Create an AgoraMusicContentCenter instance.
+ *
+ * @param config Configurations for the AgoraMusicContentCenter instance. For details, see AgoraMusicContentCenterConfig.
+ * @return An shared instance of AgoraMusicContentCenter
+*/
++ (instancetype _Nullable)sharedContentCenterWithConfig:(AgoraMusicContentCenterConfig *)config NS_SWIFT_NAME(sharedContentCenter(config:));
+
+/**
+* Renew token of music content center
+* @param token The new token.
+* @return
+* - 0: Success.
+* - < 0: Failure.
+*/
+- (NSInteger)renewToken:(NSString * _Nonnull)token;
+
+/**
+ * Register an event delegate, only the last delegate is working.
+ *
+ * @param eventDelegate the object who need AgoraRtcMediaPlayerDelegate method to get the player information ,
+ * if you want remove the delegate, just pass nil
+ * @return
+ * - 0: Success.
+ * - < 0: Failure.
+ */
+- (NSInteger)registerEventDelegate:(id _Nullable)eventDelegate;
+
+/**
+ * Creates a music player source object and return its pointer.
+ *
+ * @param delegate The object who need AgoraRtcMediaPlayerDelegate method to get the player information
+ * @return
+ * - The pointer to an object who realize the AgoraMusicPlayerProtocol, if the method call succeeds.
+ * - The empty pointer NULL, if the method call fails.
+ */
+- (id _Nullable)createMusicPlayerWithDelegate:(id _Nullable)delegate NS_SWIFT_NAME(createMusicPlayer(delegate:));
+
+/**
+ * Get music chart collection of music.If the method call success, get result from the AgoraMusicContentCenterEventDelegate - (void)onMusicChartsResult:(NSString *)requestId status:(AgoraMusicContentCenterStatusCode)status result:(NSArray *)result; match the callback "requestId" parameter to get the request result.
+ *
+ * @return The request identification
+ */
+- (NSString *)getMusicCharts;
+
+/**
+ * Get hot music list by hotType and page info.If the method call success, get result from the AgoraMusicContentCenterEventDelegate - (void)onMusicCollectionResult:(NSString *)requestId status:(AgoraMusicContentCenterStatusCode)status result:(AgoraMusicCollection *)result; match the callback "requestId" parameter to get the request result.
+ *
+ * @param musicChartId The music chart id obtained from getMusicCharts.
+ * @param page The page of the music chart, starting from 1
+ * @param pageSize The page size, max is 50.
+ * @param jsonOption The ext param, default is null.
+ * @return The request identification
+ */
+- (NSString *)getMusicCollectionWithMusicChartId:(NSInteger)musicChartId page:(NSInteger)page pageSize:(NSInteger)pageSize jsonOption:(NSString * _Nullable)jsonOption NS_SWIFT_NAME(getMusicCollection(musicChartId:page:pageSize:jsonOption:));
+
+/**
+ * Search music by keyword and page info. get result from the AgoraMusicContentCenterEventDelegate - (void)onMusicCollectionResult:(NSString *)requestId status:(AgoraMusicContentCenterStatusCode)status result:(AgoraMusicCollection *)result; match the callback "requestId" parameter to get the request result.
+ *
+ * @param keyWord The key word to search.
+ * @param page The page of the music search result, starting from 1
+ * @param pageSize The page size, max is 50.
+ * @param jsonOption The ext param, default is null.
+ * @return The request identification
+ */
+- (NSString *)searchMusicWithKeyWord:(NSString *)keyWord page:(NSInteger)page pageSize:(NSInteger)pageSize jsonOption:(NSString * _Nullable)jsonOption NS_SWIFT_NAME(searchMusic(keyWord:page:pageSize:jsonOption:));
+
+/**
+ * Preload a media file with specified parameters.
+ *
+ * @deprecated This method is deprecated. Use preload(songCode:) instead.
+ * @param songCode The identify of the media file that you want to play.
+ * @param jsonOption The ext param, default is null.
+ * @return
+ * - 0: Success.
+ * - < 0: Failure.
+ */
+- (NSInteger)preloadWithSongCode:(NSInteger)songCode jsonOption:(NSString* _Nullable)jsonOption NS_SWIFT_NAME(preload(songCode:jsonOption:)) __attribute__((deprecated("Use preload(songCode:) instead.")));
+
+/**
+ * Preload a media file with specified parameters.
+ *
+ * @param songCode The identify of the media file that you want to play.
+ * @return The request identification
+ */
+- (NSString *)preloadWithSongCode:(NSInteger)songCode NS_SWIFT_NAME(preload(songCode:));
+
+/**
+ * Preload a media file with specified parameters.
+ *
+ * @param songCode The identify of the media file that you want to play.
+ * @return
+ * - 0: Success.
+ * - < 0: Failure.
+ */
+- (NSInteger)isPreloadedWithSongCode:(NSInteger)songCode NS_SWIFT_NAME(isPreloaded(songCode:));
+
+/**
+ * Remove a media file cache
+ *
+ * @param songCode The identifier of the media file that you want to play.
+ * @return
+ * - 0: Success; the cached media file is removed.
+ * - < 0: Failure.
+ */
+- (NSInteger)removeCacheWithSongCode:(NSInteger)songCode NS_SWIFT_NAME(removeCache(songCode:));
+
+/**
+ * Get media cache files.
+ *
+ * @return The caches Array contains songCode and status of the music.
+ */
+- (NSArray *)getCaches NS_SWIFT_NAME(getCaches());
+
+/**
+ * Get internal songCodeKey from songCode and jsonOption
+ *
+ * @param songCode The identifier of the media file.
+ * @param jsonOption An extention parameter. The default value is null. it’s a json-format string and the `key` and `value` can be customized according to your scenarios.
+ * @return
+ * - Internal songCode key, if the method call succeeds.
+ * - The number less than zero, if the method call fails.
+ */
+- (NSInteger)getInternalSongCode:(NSInteger)songCode jsonOption:(NSString * _Nullable)jsonOption NS_SWIFT_NAME(getInternalSongCode(songCode:jsonOption:));
+
+/**
+ * Get lyric of the song. get result from the AgoraMusicContentCenterEventDelegate - (void)onLyricResult:(NSString*)requestId lyricUrl:(NSString*)lyricUrl; match the callback "requestId" parameter to get the request result.
+ *
+ * @param songCode The identify of the media file that you want to play.
+ * @param lyricType The type of the lyric file. may be 0:xml or 1:lrc.
+ * @return The request identification
+ */
+- (NSString *)getLyricWithSongCode:(NSInteger)songCode lyricType:(NSInteger)lyricType NS_SWIFT_NAME(getLyric(songCode:lyricType:));
+
+/**
+ * Gets the metadata of a specific music. Once this method is called, the SDK triggers the onSongSimpleInfoResult callback to report the metadata of the music.
+ *
+ * @param songCode The identify of the media file that you want to play.
+ * @return The request identification
+ */
+- (NSString *)getSongSimpleInfoWithSongCode:(NSInteger)songCode NS_SWIFT_NAME(getSongSimpleInfo(songCode:));
+
+/**
+ * If you want AgoraMusicContentCenterEventDelegate methods callback in the mainThread ,you should set enable YES. Default the delegate callback in subthread.
+ * - `NO`: (Default)Send the delegate callback in subthread.
+ * - `YES`: Send the delegate callback in mainthread.
+ */
+- (void)enableMainQueueDispatch:(BOOL)enabled;
+
+/**
+ * Destroy the shared instance of AgoraMusicContentCenter
+ *
+ * @note If you call the method, you should call it brefore AgoraRtcEngineKit destroy
+ */
++ (void)destroy;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraObjects.h b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraObjects.h
new file mode 100644
index 0000000..18b3073
--- /dev/null
+++ b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraObjects.h
@@ -0,0 +1,3284 @@
+//
+// AgoraObjects.h
+// AgoraRtcEngineKit
+//
+// Copyright (c) 2018 Agora. All rights reserved.
+//
+
+#import
+#import
+#import "AgoraEnumerates.h"
+#import "AgoraMediaFilterEventDelegate.h"
+
+#if TARGET_OS_IPHONE
+#import
+typedef UIView VIEW_CLASS;
+typedef UIColor COLOR_CLASS;
+typedef UIImage IMAGE_CLASS;
+#elif TARGET_OS_MAC
+#import
+typedef NSView VIEW_CLASS;
+typedef NSColor COLOR_CLASS;
+typedef NSImage IMAGE_CLASS;
+#endif
+
+@protocol AgoraRtcMediaPlayerProtocol;
+/**
+ * @brief The player requests to read the data callback, you need to fill the specified length of data into the buffer
+ * @param playerKit the player instance. \ref AgoraRtcMediaPlayerProtocol.
+ * @param buffer the buffer pointer that you need to fill data.
+ * @param bufferSize the bufferSize need to fill of the buffer pointer.
+ * @return you need return offset value if succeed. return 0 if failed.
+ */
+typedef int(^AgoraRtcMediaPlayerCustomSourceOnReadCallback)(id _Nonnull playerKit, unsigned char * _Nullable buffer, int bufferSize);
+
+/**
+ * @brief The Player seek event callback, you need to operate the corresponding stream seek operation, You can refer to the definition of lseek() at https://man7.org/linux/man-pages/man2/lseek.2.html
+ * @param playerKit the player instance. \ref AgoraRtcMediaPlayerProtocol.
+ * @param offset the value of seek offset,
+ * @param whence the postion of start seeking, the directive whence as follows:
+ * SEEK_SET : The file offset is set to offset bytes.
+ * SEEK_CUR : The file offset is set to its current location plus offset bytes.
+ * SEEK_END : The file offset is set to the size of the file plus offset bytes.
+ * 65536 - AVSEEK_SIZE : Optional. Passing this as the "whence" parameter to a seek function causes it to return the filesize without seeking anywhere.
+ * @return
+ * whence == 65536, return filesize if you need.
+ * whence >= 0 && whence < 3 , return offset value if succeed. return -1 if failed.
+ */
+typedef long long(^AgoraRtcMediaPlayerCustomSourceOnSeekCallback)(id _Nonnull playerKit, long long offset, int whence);
+
+__attribute__((visibility("default"))) @interface AgoraMediaSource : NSObject
+/**
+ * The URL of the media file that you want to play.
+ */
+@property(copy, nonatomic) NSString *_Nullable url;
+/**
+ * The URI of the media file.
+ */
+@property(copy, nonatomic) NSString *_Nullable uri;
+/**
+ * Set the starting position for playback, in seconds (ms)
+ */
+@property(assign, nonatomic) NSUInteger startPos;
+/**
+ * Determines whether to autoplay after opening a media resource.
+ * - `YES`: (Default) Autoplay after opening a media resource.
+ * - `NO`: Do not autoplay after opening a media resource.
+ */
+@property(assign, nonatomic) BOOL autoPlay;
+/**
+ * Determines whether to enable cache streaming to local files. If enable cached, the media player will
+ * use the url or uri as the cache index.
+ *
+ * @note
+ * The local cache function only supports on-demand video/audio streams and does not support live streams.
+ * Caching video and audio files based on the HLS protocol (m3u8) to your local device is not supported.
+ *
+ * - `YES`: Enable cache.
+ * - `NO`: (Default) Disable cache.
+ */
+@property(assign, nonatomic) BOOL enableCache;
+/**
+ * Determines whether to enable multi-track audio stream decoding.
+ * Then you can select multi audio track of the media file for playback or publish to channel
+ *
+ * @note
+ * If you use the selectMultiAudioTrack API, you must set enableMultiAudioTrack to true.
+ *
+ * - `YES`: Enable MultiAudioTrack;.
+ * - `NO`: (Default) Disable MultiAudioTrack;.
+ */
+@property(assign, nonatomic) BOOL enableMultiAudioTrack;
+/**
+ * Determines whether the opened media resource is a stream through the Agora Broadcast Streaming Network(CDN).
+ * - `YES`: It is a stream through the Agora Broadcast Streaming Network.
+ * - `NO`: (Default) It is not a stream through the Agora Broadcast Streaming Network.
+ */
+@property(assign, nonatomic) BOOL isAgoraSource;
+/**
+ * Determines whether the opened media resource is a live stream. If is a live stream, it can speed up the opening of media resources.
+ * - `YES`: It is a live stream.
+ * - `NO`: (Default) It is not is a live stream.
+ */
+@property(assign, nonatomic) BOOL isLiveSource;
+/**
+ * External custom data source callback
+ */
+@property(copy, nonatomic) AgoraRtcMediaPlayerCustomSourceOnReadCallback _Nonnull playerOnReadCallback;
+@property(copy, nonatomic) AgoraRtcMediaPlayerCustomSourceOnSeekCallback _Nonnull playerOnSeekCallback;
+
+@end
+
+__attribute__((visibility("default"))) @interface AgoraMediaPlayerCacheStatistics : NSObject
+
+@property(assign, nonatomic) NSInteger fileSize;
+@property(assign, nonatomic) NSInteger cacheSize;
+@property(assign, nonatomic) NSInteger downloadSize;
+
+@end
+
+/**
+ * @brief player_id and device_id has value when user trigger interface of opening.
+ *
+ */
+__attribute__((visibility("default"))) @interface AgoraMediaPlayerUpdatedInfo : NSObject
+@property(copy, nonatomic) NSString *_Nullable playerId;
+@property(copy, nonatomic) NSString *_Nullable deviceId;
+@property(strong, nonatomic) AgoraMediaPlayerCacheStatistics *_Nullable cacheStatistics;
+@end
+
+/**
+ * @brief The information of the media stream object.
+ *
+ */
+__attribute__((visibility("default"))) @interface AgoraMediaPlayerSrcInfo : NSObject
+/**
+ * The bitrate of the media stream. The unit of the number is kbps.
+ */
+@property(assign, nonatomic) int bitrateInKbps;
+/**
+ * The name of the media stream.
+*/
+@property(copy, nonatomic) NSString *_Nullable name;
+
+@end
+
+
+/**
+ * The statistics of the Direct Cdn Streams.
+ */
+__attribute__((visibility("default"))) @interface AgoraDirectCdnStreamingStats : NSObject
+/**
+ * Width of the video pushed by rtmp.
+ */
+@property(assign, nonatomic) NSUInteger videoWidth;
+/**
+ * Height of the video pushed by rtmp.
+ */
+@property(assign, nonatomic) NSUInteger videoHeight;
+/**
+ * The frame rate of the video pushed by rtmp.
+ */
+@property(assign, nonatomic) NSUInteger fps;
+/**
+ * Real-time bit rate of the video streamed by rtmp.
+ */
+@property(assign, nonatomic) NSUInteger videoBitrate;
+/**
+ * Real-time bit rate of the audio pushed by rtmp.
+ */
+@property(assign, nonatomic) NSUInteger audioBitrate;
+
+@end
+
+/**
+ * The cdn streaming media options.
+ */
+__attribute__((visibility("default"))) @interface AgoraDirectCdnStreamingMediaOptions : NSObject
+/**
+ * Determines whether to publish the video of the camera track.
+ * - `YES`: Publish the video track of the camera capturer.
+ * - `NO`: (Default) Do not publish the video track of the camera capturer.
+ */
+@property(assign, nonatomic) BOOL publishCameraTrack;
+/**
+ * Determines whether to publish the recorded audio.
+ * - `YES`: Publish the recorded audio.
+ * - `NO`: (Default) Do not publish the recorded audio.
+ */
+@property(assign, nonatomic) BOOL publishMicrophoneTrack;
+/**
+ * Determines whether to publish the audio of the custom audio track.
+ * - `YES`: Publish the audio of the custom audio track.
+ * - `NO`: (Default) Do not publish the audio of the custom audio track.
+ */
+@property(assign, nonatomic) BOOL publishCustomAudioTrack;
+/**
+ * Determines whether to publish the video of the custom video track.
+ * - `YES`: Publish the video of the custom video track.
+ * - `NO`: (Default) Do not publish the video of the custom video track.
+ */
+@property(assign, nonatomic) BOOL publishCustomVideoTrack;
+/**
+ * Determines whether to publish the audio track of media player source.
+ * - `YES`: Publish the audio track of media player source.
+ * - `NO`: (Default) Do not publish the audio track of media player source.
+*/
+@property(assign, nonatomic) BOOL publishMediaPlayerAudioTrack;
+/**
+ * Determines which media player source should be published.
+ * This parameter get from function getMediaPlayerId() of AgoraMediaPlayer.
+*/
+@property(assign, nonatomic) NSInteger publishMediaPlayerId;
+
+/**
+ * The custom video track id which will used to publish.
+ */
+@property(assign, nonatomic) NSInteger customVideoTrackId;
+
+@end
+
+/**
+ * The video encoded track options.
+ */
+__attribute__((visibility("default"))) @interface AgoraEncodedVideoTrackOptions : NSObject
+/**
+ * Whether to enable CC mode.
+ * - TCC_ENABLED = 0: (Default) enable cc.
+ * - TCC_DISABLED = 1: disable cc.
+ */
+@property(assign, nonatomic) int ccMode;
+/**
+ * The codec type used for the encoded images.
+ * - VIDEO_CODEC_VP8 = 1: VP8.
+ * - VIDEO_CODEC_H264 = 2: (Default) H.264.
+ * - VIDEO_CODEC_H265 = 3: H.265.
+ * - VIDEO_CODEC_VP9 = 5: VP9.
+ * - VIDEO_CODEC_GENERIC = 6: GENERIC.
+ * - VIDEO_CODEC_GENERIC_H264 = 7: GENERIC_H264.
+ * - VIDEO_CODEC_GENERIC_JPEG = 20: GENERIC_JPEG.
+ */
+@property(assign, nonatomic) int codecType;
+/**
+ * Target bitrate (Kbps) for sending encoded video frame.
+ */
+@property(assign, nonatomic) int targetBitrate;
+@end
+
+/**
+ * The channel media options.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcChannelMediaOptions : NSObject
+/**
+ * Determines whether to publish the video of the camera track.
+ * - `YES`: (Default) Publish the video track of the camera capturer.
+ * - `NO`: Do not publish the video track of the camera capturer.
+ */
+@property(assign, nonatomic) BOOL publishCameraTrack;
+/**
+ * Determines whether to publish the video of the secondary camera track.
+ * - `YES`: Publish the video track of the secondary camera capturer.
+ * - `NO`: (Default) Do not publish the video track of the secondary camera capturer.
+ */
+@property(assign, nonatomic) BOOL publishSecondaryCameraTrack;
+/**
+ * Determines whether to publish the recorded audio of microphone.
+ * - `YES`: (Default) Publish the recorded audio of microphone.
+ * - `NO`: Do not publish the recorded audio of microphone.
+ */
+@property(assign, nonatomic) BOOL publishMicrophoneTrack;
+#if TARGET_OS_IPHONE
+/**
+ * Determines whether to publish the video of the screen capturer.
+ * - `YES`: Publish the video track of the screen capturer.
+ * - `NO`: (Default) Do not publish the video track of the screen capturer.
+ */
+@property(assign, nonatomic) BOOL publishScreenCaptureVideo;
+/**
+ * Determines whether to publish the audio of the screen capturer.
+ * - `YES`: Publish the audio track of the screen capturer.
+ * - `NO`: (Default) Do not publish the audio track of the screen capturer.
+ */
+@property(assign, nonatomic) BOOL publishScreenCaptureAudio;
+#elif TARGET_OS_MAC
+/**
+ * Determines whether to publish the video of the third camera track.
+ * - `YES`: Publish the video track of the third camera capturer.
+ * - `NO`: (Default) Do not publish the video track of the third camera capturer.
+ */
+@property(assign, nonatomic) BOOL publishThirdCameraTrack;
+/**
+ * Determines whether to publish the video of the fourth camera track.
+ * - `YES`: Publish the video track of the fourth camera capturer.
+ * - `NO`: (Default) Do not publish the video track of the fourth camera capturer.
+ */
+@property(assign, nonatomic) BOOL publishFourthCameraTrack;
+/**
+ * Determines whether to publish the video of the screen capturer.
+ * - `YES`: Publish the video track of the screen capturer.
+ * - `NO`: (Default) Do not publish the video track of the screen capturer.
+ */
+@property(assign, nonatomic) BOOL publishScreenTrack;
+/**
+ * Determines whether to publish the video of the secondary screen track.
+ * - `YES`: Publish the video track of the secondary screen capturer.
+ * - `NO`: (Default) Do not publish the video track of the secondary screen capturer.
+ */
+@property(assign, nonatomic) BOOL publishSecondaryScreenTrack;
+/**
+ * Determines whether to publish the video of the third screen track.
+ * - `YES`: Publish the video track of the secondary third capturer.
+ * - `NO`: (Default) Do not publish the video track of the third screen capturer.
+ */
+@property(assign, nonatomic) BOOL publishThirdScreenTrack;
+/**
+ * Determines whether to publish the video of the fourth screen track.
+ * - `YES`: Publish the video track of the secondary fourth capturer.
+ * - `NO`: (Default) Do not publish the video track of the fourth screen capturer.
+ */
+@property(assign, nonatomic) BOOL publishFourthScreenTrack;
+#endif
+/**
+ * Determines whether to publish the audio of the custom audio track.
+ * - `YES`: Publish the audio of the custom audio track.
+ * - `NO`: (Default) Do not publish the audio of the custom audio track.
+ */
+@property(assign, nonatomic) BOOL publishCustomAudioTrack;
+/**
+ * The custom audio track id. The default value is 0.
+ */
+@property(assign, nonatomic) NSInteger publishCustomAudioTrackId;
+/**
+ * Determines whether to publish AEC custom audio track.
+ * - `YES`: Publish AEC track.
+ * - `NO`: (Default) Do not publish AEC track.
+ */
+@property(assign, nonatomic) BOOL publishCustomAudioTrackAec;
+/**
+ * Determines whether to publish the video of the custom video track.
+ * - `YES`: Publish the video of the custom video track.
+ * - `NO`: (Default) Do not publish the video of the custom video track.
+ */
+@property(assign, nonatomic) BOOL publishCustomVideoTrack;
+/**
+ * Determines whether to publish the video of the encoded video track.
+ * - `YES`: Publish the video of the encoded video track.
+ * - `NO`: (Default) Do not publish the video of the encoded video track.
+ */
+@property(assign, nonatomic) BOOL publishEncodedVideoTrack;
+/**
+ * Determines whether to publish the audio track of media player.
+ * - `YES`: Publish the audio track of media player.
+ * - `NO`: (Default) Do not publish the audio track of media player.
+ */
+@property(assign, nonatomic) BOOL publishMediaPlayerAudioTrack;
+/**
+* Determines whether to publish the video track of media player source.
+* - `YES`: Publish the video track of media player source.
+* - `NO`: (Default) Do not publish the video track of media player source.
+*/
+@property(assign, nonatomic) BOOL publishMediaPlayerVideoTrack;
+/**
+* Determines whether to publish the local transcoded video track.
+* - `YES`: Publish the video track of local transcoded video track.
+* - `NO`: (Default) Do not publish the local transcoded video track.
+*/
+@property(assign, nonatomic) BOOL publishTrancodedVideoTrack;
+/**
+* Determines whether to publish the local mixed audio track.
+* - `YES`: Publish the audio track of local mixed audio track.
+* - `NO`: (Default) Do not publish the local mixed audio track.
+*/
+@property(assign, nonatomic) BOOL publishMixedAudioTrack;
+/**
+ * Determines whether to subscribe all remote audio streams automatically.
+ * This property replaces calling \ref AgoraRtcEngineKit.setDefaultMuteAllRemoteAudioStreams: setDefaultMuteAllRemoteAudioStreams
+ * before joining a channel.
+ * - `YES`: (Default) Subscribe all remote audio streams automatically.
+ * - `NO`: Do not subscribe any remote audio stream automatically.
+ */
+@property(assign, nonatomic) BOOL autoSubscribeAudio;
+/**
+ * Determines whether to subscribe all remote video streams automatically.
+ * This property replaces calling \ref AgoraRtcEngineKit.setDefaultMuteAllRemoteVideoStreams: setDefaultMuteAllRemoteVideoStreams
+ * before joining a channel.
+ * - `YES`: (Default) Subscribe all remote video streams automatically.
+ * - `NO`: Do not subscribe any remote video stream automatically.
+ */
+@property(assign, nonatomic) BOOL autoSubscribeVideo;
+/**
+ * Determines whether to enable audio recording or playout.
+ * - `YES`: (Default) It's used to publish audio and mix microphone, or subscribe audio and playout.
+ * - `NO`: It's used to publish extenal audio frame only without mixing microphone, or no need audio device to playout audio either.
+ */
+@property(assign, nonatomic) BOOL enableAudioRecordingOrPlayout;
+/**
+* Determines which media player source should be published.
+* This parameter get from function getMediaPlayerId() of AgoraMediaPlayer.
+*/
+@property(assign, nonatomic) NSInteger publishMediaPlayerId;
+/**
+ * The client role type: \ref AgoraClientRole.
+ * Default is AgoraClientRoleAudience.
+ */
+@property(assign, nonatomic) AgoraClientRole clientRoleType;
+/**
+ * The audience latency level type: \ref AgoraAudienceLatencyLevelType.
+ * Default is AgoraAudienceLatencyLevelUltraLowLatency.
+ */
+@property(assign, nonatomic) AgoraAudienceLatencyLevelType audienceLatencyLevel;
+/**
+ * The default video stream type: \ref AgoraVideoStreamType.
+ * Default is AgoraVideoStreamTypeHigh.
+ */
+@property(assign, nonatomic) AgoraVideoStreamType defaultVideoStreamType;
+/**
+ * The channel profile: \ref AgoraChannelProfile.
+ * Default is AgoraChannelProfileLiveBroadcasting.
+ */
+@property(assign, nonatomic) AgoraChannelProfile channelProfile;
+/**
+ * The delay in ms for sending audio frames. This is used for explicit control of A/V sync.
+ * To switch off the delay, set the value to zero.
+ */
+@property(assign, nonatomic) NSInteger audioDelayMs;
+/**
+ * The delay in ms for sending media player audio frames. This is used for explicit control of A/V sync.
+ * To switch off the delay, set the value to zero.
+ */
+@property(assign, nonatomic) NSInteger mediaPlayerAudioDelayMs;
+/**
+ * The token to be renewed.
+ */
+@property(copy, nonatomic) NSString * _Nullable token;
+/**
+ * Enable media packet encryption.
+ * It will be ignored when calling function updateChannelMediaOptions().
+ * - `YES`: Enable media packet encryption.
+ * - `NO`: (Default) Do not Enable media packet encryption.
+ */
+@property(assign, nonatomic) BOOL enableBuiltInMediaEncryption;
+
+/**
+ * Determines whether to publish the sound of the rhythm player to remote users.
+ * - true: (Default) Publish the sound of the rhythm player.
+ * - false: Do not publish the sound of the rhythm player.
+ */
+@property(assign, nonatomic) BOOL publishRhythmPlayerTrack;
+/**
+ * This mode is only used for audience. In PK mode, client might join one
+ * channel as broadcaster, and join another channel as interactive audience to
+ * achieve low lentancy and smooth video from remote user.
+ * - `YES`: Enable low lentancy and smooth video when joining as an audience.
+ * - `NO`: (default) Use default settings for audience role.
+ */
+@property(assign, nonatomic) BOOL isInteractiveAudience;
+
+/**
+ * The custom video track id which will used to publish or preview.
+ */
+@property(assign, nonatomic) NSInteger customVideoTrackId;
+
+/**
+ * Determines whether local audio stream can be filtered.
+ * - `YES`: (Default) Can be filtered when audio level is low.
+ * - `NO`: Do not filter this audio stream.
+ */
+@property(assign, nonatomic) BOOL isAudioFilterable;
+
+/** Provides the technical preview functionalities or special customizations by configuring the SDK with JSON options.
+ */
+@property(copy, nonatomic) NSString * _Nullable parameters;
+
+@end
+
+/** Properties of the video canvas object.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcVideoCanvas : NSObject
+/**
+ *The video display view. The SDK does not maintain the lifecycle of the view.
+ *
+ *The view can be safely released after calling [leaveChannel]([AgoraRtcEngineKit
+ *leaveChannel:]) with a returned value. The SDK keeps a cache of the view value, so calling
+ *[setupLocalVideo]([AgoraRtcEngineKit setupLocalVideo:]) to set the view value to nil can
+ *clear the cache before switching or releasing the view.
+ */
+@property(strong, nonatomic) VIEW_CLASS *_Nullable view;
+/**
+ * The user id of local video.
+ */
+@property(assign, nonatomic) NSUInteger uid;
+
+@property(assign, nonatomic) NSUInteger subviewUid;
+
+/**
+ * The video render mode. See \ref AgoraVideoRenderMode.
+ * The default value is AgoraVideoRenderModeHidden.
+ */
+@property(assign, nonatomic) AgoraVideoRenderMode renderMode;
+/**
+ * The video mirror mode. See \ref AgoraVideoMirrorMode.
+ * The default value is AgoraVideoMirrorModeAuto.
+ * @note
+ * - For the mirror mode of the local video view:
+ * If you use a front camera, the SDK enables the mirror mode by default;
+ * if you use a rear camera, the SDK disables the mirror mode by default.
+ * - For the remote user: The mirror mode is disabled by default.
+ */
+@property(assign, nonatomic) AgoraVideoMirrorMode mirrorMode;
+/**
+ * The mode of setting up video view. See \ref AgoraVideoViewSetupMode.
+ * The default value is AgoraVideoViewSetupReplace.
+ */
+@property(assign, nonatomic) AgoraVideoViewSetupMode setupMode;
+/**
+ * The video source type. See \ref AgoraVideoSourceType
+ * The default value is AgoraVideoSourceTypeCamera.
+ */
+@property(nonatomic, assign) AgoraVideoSourceType sourceType;
+/**
+ * The media player id of AgoraMediaPlayer. It should set this parameter when the
+ * sourceType is AgoraVideoSourceTypeMediaPlayer to show the video that AgoraMediaPlayer is playing.
+ * You can get this value by calling the method \ref getMediaPlayerId().
+ */
+@property(nonatomic, assign) int mediaPlayerId;
+/**
+ * If you want to display a certain part of a video frame, you can set
+ * this value to crop the video frame to show.
+ * The default value is empty(that is, if it has zero width or height), which means no cropping.
+ */
+@property(assign, nonatomic) CGRect cropArea;
+/**
+ * default NO. if set to YES, the video will apply alpha mask if exist.(Mac only)
+ */
+@property(assign, nonatomic) BOOL enableAlphaMask;
+
+@end
+
+/**
+ * The configurations for the last-mile network probe test.
+ */
+__attribute__((visibility("default"))) @interface AgoraLastmileProbeConfig : NSObject
+/**
+ * Sets whether or not to test the uplink network.
+ *
+ * Some users, for example, the audience in a live-broadcast channel, do not need such a test.
+ * - `YES`: Enables the test.
+ * - `NO`: Disables the test.
+ */
+@property (assign, nonatomic) BOOL probeUplink;
+/**
+ * Sets whether or not to test the downlink network.
+ * - `YES`: Enables the test.
+ * - `NO`: Disables the test.
+ */
+@property (assign, nonatomic) BOOL probeDownlink;
+/**
+ * Sets the expected maximum sending bitrate (bps) of the local user.
+ *
+ * The value ranges between 100000 and 5000000. Agora recommends
+ * setting this value according to the required bitrate of selected video profile.
+ */
+@property (assign, nonatomic) NSUInteger expectedUplinkBitrate;
+/**
+ * Sets the expected maximum receiving bitrate (bps) of the local user.
+ * The value ranges between 100000 and 5000000.
+ */
+@property (assign, nonatomic) NSUInteger expectedDownlinkBitrate;
+@end
+
+/**
+ * The one-way last-mile probe result.
+ */
+__attribute__((visibility("default"))) @interface AgoraLastmileProbeOneWayResult : NSObject
+/**
+ * The packet loss rate (%).
+ */
+@property (assign, nonatomic) NSUInteger packetLossRate;
+/**
+ * The network jitter (ms).
+ */
+@property (assign, nonatomic) NSUInteger jitter;
+/**
+ * The estimated available bandwidth (bps).
+ */
+@property (assign, nonatomic) NSUInteger availableBandwidth;
+@end
+
+/**
+ * Statistics of the last-mile probe.
+ */
+__attribute__((visibility("default"))) @interface AgoraLastmileProbeResult : NSObject
+/**
+ * The state of the probe test.
+ * See \ref AgoraLastmileProbeResultState.
+ */
+@property (assign, nonatomic) AgoraLastmileProbeResultState state;
+/**
+ * The round-trip delay time (ms).
+ */
+@property (assign, nonatomic) NSUInteger rtt;
+/**
+ * The uplink last-mile network report.
+ *
+ * See \ref AgoraLastmileProbeOneWayResult.
+ */
+@property (strong, nonatomic) AgoraLastmileProbeOneWayResult *_Nonnull uplinkReport;
+/**
+ * The downlink last-mile network report.
+ *
+ * See \ref AgoraLastmileProbeOneWayResult.
+ */
+@property (strong, nonatomic) AgoraLastmileProbeOneWayResult *_Nonnull downlinkReport;
+@end
+
+
+/**
+ * The statistics of the local video stream.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcLocalVideoStats : NSObject
+/**
+ * Bitrate (Kbps) sent in the reported interval, which does not include
+ * the bitrate of the retransmission video after packet loss.
+ */
+@property(assign, nonatomic) NSUInteger sentBitrate;
+/**
+ * Frame rate (fps) sent in the reported interval, which does not include
+ * the frame rate of the retransmission video after packet loss.
+ */
+@property(assign, nonatomic) NSUInteger sentFrameRate;
+/**
+ * ID of the local user.
+ */
+@property(assign, nonatomic) NSUInteger uid;
+
+/** The capture frame rate (fps) of the local video.
+ */
+@property(assign, nonatomic) NSInteger captureFrameRate;
+/** The width of the capture frame (px).
+ */
+@property(assign, nonatomic) NSInteger captureFrameWidth;
+/** The height of the capture frame (px).
+ */
+@property(assign, nonatomic) NSInteger captureFrameHeight;
+/**
+ * The regulated frame rate of capture frame rate according to video encoder configuration.
+ */
+@property(assign, nonatomic) NSInteger regulatedCaptureFrameRate;
+/**
+ * The regulated frame width (pixel) of capture frame width according to video encoder configuration.
+ */
+@property(assign, nonatomic) NSInteger regulatedCaptureFrameWidth;
+/**
+ * The regulated frame height (pixel) of capture frame height according to video encoder configuration.
+ */
+@property(assign, nonatomic) NSInteger regulatedCaptureFrameHeight;
+
+/** The encoder output frame rate (fps) of the local video.
+ */
+@property(assign, nonatomic) NSInteger encoderOutputFrameRate;
+/** The render output frame rate (fps) of the local video.
+ */
+@property(assign, nonatomic) NSInteger rendererOutputFrameRate;
+/** The target frame rate (fps) of the current encoder.
+ */
+@property(assign, nonatomic) NSInteger targetFrameRate;
+/** Quality change of the local video in terms of target frame rate and target bit rate in this reported interval, see [AgoraVideoQualityAdaptIndication](AgoraVideoQualityAdaptIndication). */
+@property(assign, nonatomic) AgoraVideoQualityAdaptIndication qualityAdaptIndication;
+/**
+ * The target bitrate (Kbps) of the current encoder. This value is
+ * estimated by the SDK based on the current network conditions.
+ */
+@property(assign, nonatomic) NSInteger targetBitrate;
+/**
+ * The encoding bitrate (Kbps), which does not include the bitrate of the
+ * re-transmission video after packet loss.
+ */
+@property(assign, nonatomic) NSInteger encodedBitrate;
+/**
+ * The width of the encoding frame (px).
+ */
+@property(assign, nonatomic) NSInteger encodedFrameWidth;
+/**
+ * The height of the encoding frame (px).
+ */
+@property(assign, nonatomic) NSInteger encodedFrameHeight;
+/**
+ * The number of the sent frames, represented by an aggregate value.
+ */
+@property(assign, nonatomic) NSInteger encodedFrameCount;
+/**
+ * The codec type of the local video:
+ * - VIDEO_CODEC_VP8 = 1: VP8.
+ * - VIDEO_CODEC_H264 = 2: (Default) H.264.
+ */
+@property(assign, nonatomic) AgoraVideoCodecType codecType;
+/**
+ * The hw_encoder_accelerating of the local video:
+ * - hwEncoderAccelerating = 0: the encoder is software
+ * - hwEncoderAccelerating = 1: the encoder is hardware
+ */
+@property(assign, nonatomic) AgoraVideoHwEncoderAccelerating hwEncoderAccelerating;
+/**
+ * The video packet loss rate (%) from the local client to the Agora edge server before applying the anti-packet loss strategies.
+ */
+@property(assign, nonatomic) NSInteger txPacketLossRate;
+/**
+ * The brightness level of the video image captured by the local camera. See AgoraCaptureBrightnessLevelType.
+ */
+@property(assign, nonatomic) AgoraCaptureBrightnessLevelType captureBrightnessLevel NS_SWIFT_NAME(captureBrightnessLevel);
+/**
+ * Whether we send dual stream now.
+ */
+@property(assign, nonatomic) BOOL dualStreamEnabled;
+@end
+
+/** Statistics of the remote video stream. */
+__attribute__((visibility("default"))) @interface AgoraRtcRemoteVideoStats : NSObject
+/**
+ * ID of the remote user sending the video stream.
+ */
+@property(assign, nonatomic) NSUInteger uid;
+/** Time delay (ms).
+ */
+@property(assign, nonatomic) NSUInteger delay __deprecated;
+/** Width (pixels) of the video stream.
+ */
+@property(assign, nonatomic) NSUInteger width;
+/** Height (pixels) of the video stream.
+ */
+@property(assign, nonatomic) NSUInteger height;
+/** Data receive bitrate (Kbps) since last count.
+ */
+@property(assign, nonatomic) NSUInteger receivedBitrate;
+/** Data receive frame rate (fps) since last count.
+ */
+@property(assign, nonatomic) NSUInteger receivedFrameRate;
+/** Video stream type; high- or low-video stream.
+ */
+@property(assign, nonatomic) AgoraVideoStreamType rxStreamType;
+
+/** The decoder output frame rate (fps) of the remote video.
+ */
+@property(assign, nonatomic) NSInteger decoderOutputFrameRate;
+/** The render output frame rate (fps) of the remote video.
+ */
+@property(assign, nonatomic) NSInteger rendererOutputFrameRate;
+/** The video frame loss rate (%) of the remote video stream in the reported interval.
+ */
+@property(assign, nonatomic) NSInteger frameLossRate;
+/** Packet loss rate (%) of the remote video stream after using the anti-packet-loss method.
+ */
+@property(assign, nonatomic) NSInteger packetLossRate;
+/**
+ The total freeze time (ms) of the remote video stream after the remote user joins the channel.
+ In a video session where the frame rate is set to no less than 5 fps, video freeze occurs when
+ the time interval between two adjacent renderable video frames is more than 500 ms.
+ */
+@property(assign, nonatomic) NSInteger totalFrozenTime;
+/**
+ * The total time (ms) when the remote user neither stops sending the audio
+ * stream nor disables the audio module after joining the channel.
+ */
+@property(assign, nonatomic) NSUInteger totalActiveTime;
+/**
+ * The total publish duration (ms) of the remote audio stream.
+ */
+@property(assign, nonatomic) NSInteger publishDuration;
+/**
+ The total video freeze time as a percentage (%) of the total time when the video is available.
+ */
+@property(assign, nonatomic) NSInteger frozenRate;
+/**
+ The offset (ms) between audio and video stream. A positive value indicates the audio leads the
+ video, and a negative value indicates the audio lags the video.
+ */
+@property(assign, nonatomic) NSInteger avSyncTimeMs;
+/**
+ * The quality of the remote video stream in the reported interval.
+ * The quality is determined by the Agora real-time video MOS (Mean Opinion Score) measurement method.
+ * The return value range is [0, 500].
+ * Dividing the return value by 100 gets the MOS score, which ranges from 0 to 5. The higher the score, the better the video quality.
+ * @note For textured video data, this parameter always returns 0.
+ */
+@property(assign, nonatomic) NSInteger mosValue;
+/**
+ * Total number of video bytes received (bytes), represented by an aggregate value.
+ */
+@property(assign, nonatomic) NSUInteger rxVideoBytes;
+
+@end
+
+/**
+ * The statistics of the local audio.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcLocalAudioStats : NSObject
+/**
+ * The number of audio channels.
+ */
+@property(assign, nonatomic) NSUInteger numChannels;
+/**
+ * The sample rate (Hz).
+ */
+@property(assign, nonatomic) NSUInteger sentSampleRate;
+/**
+ * The average sending bitrate (Kbps).
+ */
+@property(assign, nonatomic) NSUInteger sentBitrate;
+/** The internal payload type.
+ */
+@property(assign, nonatomic) NSUInteger internalCodec;
+/** The audio packet loss rate (%) from the local client to the Agora edge server before applying the anti-packet loss strategies.
+ */
+@property(assign, nonatomic) NSUInteger txPacketLossRate;
+/**
+ * The audio delay of the device, contains record and playout delay
+ */
+@property(assign, nonatomic) NSUInteger audioDeviceDelay;
+/**
+ * The audio playout delay of the device
+ */
+@property(assign, nonatomic) NSUInteger audioPlayoutDelay;
+/**
+ * The estimated delay of audio in-ear monitoring
+ */
+@property(assign, nonatomic) NSUInteger earMonitorDelay;
+/**
+ * The estimated signal delay (ms) from AEC nearin and farin
+ */
+@property(assign, nonatomic) NSUInteger aecEstimatedDelay;
+/**
+ * The AIMD result
+ */
+@property(assign, nonatomic) NSInteger aedMusicRes;
+/**
+ * The AIVAD result
+ */
+@property(assign, nonatomic) NSInteger aedVoiceRes;
+
+@end
+
+/**
+ * The statistics of the remote audio.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcRemoteAudioStats : NSObject
+/**
+ * ID of the user sending the audio stream.
+ */
+@property(assign, nonatomic) NSUInteger uid;
+/**
+ * The receiving audio quality.
+ *
+ * - 0: The quality is unknown.
+ * - 1: The quality is excellent.
+ * - 2: The quality is quite good, but the bitrate may be slightly
+ * lower than excellent.
+ * - 3: Users can feel the communication slightly impaired.
+ * - 4: Users can communicate not very smoothly.
+ * - 5: The quality is so bad that users can barely communicate.
+ * - 6: The network is disconnected and users cannot communicate at all.
+ */
+@property(assign, nonatomic) NSUInteger quality;
+/**
+ * The network delay (ms) from the sender to the receiver.
+ */
+@property(assign, nonatomic) NSUInteger networkTransportDelay;
+/**
+ * The jitter buffer delay (ms) at the receiver.
+ */
+@property(assign, nonatomic) NSUInteger jitterBufferDelay;
+/**
+ * The packet loss rate in the reported interval.
+ */
+@property(assign, nonatomic) NSUInteger audioLossRate;
+/**
+ * The number of audio channels.
+ */
+@property(assign, nonatomic) NSUInteger numChannels;
+/**
+ * The sample rate (Hz) of the received audio stream, represented by an instantaneous value.
+ */
+@property(assign, nonatomic) NSUInteger receivedSampleRate;
+/**
+ * The bitrate (Kbps) of the received audio stream, represented by an instantaneous value.
+ */
+@property(assign, nonatomic) NSUInteger receivedBitrate;
+/**
+ * The total freeze time (ms) of the remote audio stream after the remote user joins the channel.
+ * In a session, audio freeze occurs when the audio frame loss rate reaches 4% within two seconds.
+ * Agora uses 2 seconds as an audio piece unit to calculate the audio freeze time.
+ * The total audio freeze time = The audio freeze number × 2 seconds
+ */
+@property(assign, nonatomic) NSUInteger totalFrozenTime;
+/**
+ * The total time (ms) when the remote user neither stops sending the audio
+ * stream nor disables the audio module after joining the channel.
+ */
+@property(assign, nonatomic) NSUInteger totalActiveTime;
+/**
+ * The total publish duration (ms) of the remote audio stream.
+ */
+@property(assign, nonatomic) NSInteger publishDuration;
+/**
+ * The total audio freeze time as a percentage (%) of the total time when the audio is available.
+ */
+@property(assign, nonatomic) NSUInteger frozenRate;
+/**
+ * The quality of the remote audio stream as determined by the Agora real-time
+ * audio MOS (Mean Opinion Score) measurement method in the reported interval.
+ * The return value ranges from 0 to 500. Dividing the return value by 100 gets
+ * the MOS score, which ranges from 0 to 5. The higher the score, the better the audio quality.
+ *
+ * The subjective perception of audio quality corresponding to the Agora real-time audio MOS scores is as follows:
+ *
+ * | MOS score | Perception of audio quality |
+ * | :------------- | :----------------------------------------------------------- |
+ * | Greater than 4 | Excellent. The audio sounds clear and smooth. |
+ * | From 3.5 to 4 | Good. The audio has some perceptible impairment, but still sounds clear. |
+ * | From 3 to 3.5 | Fair. The audio freezes occasionally and requires attentive listening. |
+ * | From 2.5 to 3 | Poor. The audio sounds choppy and requires considerable effort to understand. |
+ * | From 2 to 2.5 | Bad. The audio has occasional noise. Consecutive audio dropouts occur, resulting in some information loss. The users can communicate only with difficulty. |
+ * | Less than 2 | Very bad. The audio has persistent noise. Consecutive audio dropouts are frequent, resulting in severe information loss. Communication is nearly impossible. |
+ */
+@property(assign, nonatomic) NSUInteger mosValue;
+/**
+ * Quality of experience (QoE) of the local user when receiving a remote audio stream.
+ */
+@property(assign, nonatomic) AgoraExperienceQuality qoeQuality;
+/**
+ * The reason for poor QoE of the local user when receiving a remote audio stream. See #EXPERIENCE_POOR_REASON.
+ */
+@property(assign, nonatomic) AgoraExperiencePoorReason qualityChangedReason;
+/**
+ * Total number of audio bytes received (bytes) before network countermeasures, represented by
+ * an aggregate value.
+ */
+@property(assign, nonatomic) NSUInteger rxAudioBytes;
+/**
+ * The end-to-end delay (ms) from the sender to the receiver.
+ */
+@property(assign, nonatomic) NSInteger e2eDelay;
+@end
+
+/** Properties of the audio volume information.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSObject
+/** User ID of the speaker.
+ */
+@property(assign, nonatomic) NSUInteger uid;
+/** The volume of the speaker that ranges from 0 (lowest volume) to 255 (highest volume).
+ */
+@property(assign, nonatomic) NSUInteger volume;
+
+@property(assign, nonatomic) NSUInteger vad;
+
+/** Voice pitch frequency in Hz.
+ */
+@property (assign, nonatomic) double voicePitch;
+
+@end
+
+/**
+ * The Statistics of the channel.
+ */
+__attribute__((visibility("default"))) @interface AgoraChannelStats : NSObject
+/**
+ * The call duration in seconds, represented by an aggregate value.
+ */
+@property(assign, nonatomic) NSUInteger duration;
+/**
+ * The total number of bytes transmitted, represented by an aggregate value.
+ */
+@property(assign, nonatomic) NSUInteger txBytes;
+/**
+ * The total number of bytes received, represented by an aggregate value.
+ */
+@property(assign, nonatomic) NSUInteger rxBytes;
+/**
+ * The audio transmission bitrate in Kbps, represented by an instantaneous value.
+ */
+@property(assign, nonatomic) NSUInteger txAudioKBitrate;
+/**
+ * The audio receiving bitrate in Kbps, represented by an instantaneous value.
+ */
+@property(assign, nonatomic) NSUInteger rxAudioKBitrate;
+/**
+ * The video transmission bitrate in Kbps, represented by an instantaneous value.
+ */
+@property(assign, nonatomic) NSUInteger txVideoKBitrate;
+/**
+ * The video receiving bitrate in Kbps, represented by an instantaneous value.
+ */
+@property(assign, nonatomic) NSUInteger rxVideoKBitrate;
+/**
+ * Total number of audio bytes sent (bytes), represented by an aggregate value.
+ */
+@property(assign, nonatomic) NSUInteger txAudioBytes;
+/**
+ * Total number of video bytes sent (bytes), represented by an aggregate value.
+ */
+@property(assign, nonatomic) NSUInteger txVideoBytes;
+/**
+ * Total number of audio bytes received (bytes) before network countermeasures, represented by
+ * an aggregate value.
+ */
+@property(assign, nonatomic) NSUInteger rxAudioBytes;
+/**
+ * Total number of video bytes received (bytes), represented by an aggregate value.
+ */
+@property(assign, nonatomic) NSUInteger rxVideoBytes;
+/**
+ * The client-server latency (ms).
+ */
+@property(assign, nonatomic) NSUInteger lastmileDelay;
+/**
+ * The number of users in the channel.
+ */
+@property(assign, nonatomic) NSUInteger userCount;
+/** Application CPU usage (%).
+ */
+@property(assign, nonatomic) double cpuAppUsage;
+/** System CPU usage (%).
+ */
+@property(assign, nonatomic) double cpuTotalUsage;
+/** Gateway Rtt.
+ */
+@property(assign, nonatomic) NSInteger gatewayRtt;
+/**
+ * The memory usage ratio of the app (%).
+ */
+@property(assign, nonatomic) double memoryAppUsageRatio;
+/**
+ * The memory usage ratio of the system (%).
+ */
+@property(assign, nonatomic) double memoryTotalUsageRatio;
+/**
+ * The memory usage of the app (KB).
+ */
+@property(assign, nonatomic) NSInteger memoryAppUsageInKbytes;
+/**
+ * The time interval (ms) between establishing the connection and the connection succeeds, 0 if not valid.
+ */
+@property(assign, nonatomic) NSInteger connectTimeMs;
+
+/**
+ * The transmission bitrate in Kbps, represented by an instantaneous value.
+ */
+@property(assign, nonatomic) NSUInteger txKBitrate;
+/**
+ * The receiving bitrate in Kbps, represented by an instantaneous value.
+ */
+@property(assign, nonatomic) NSUInteger rxKBitrate;
+
+/**The duration(ms) between first audio packet received and connection start, 0 if not valid
+ */
+@property(assign, nonatomic) NSInteger firstAudioPacketDuration;
+/** The duration(ms) between first video packet received and connection start, 0 if not valid
+ */
+@property(assign, nonatomic) NSInteger firstVideoPacketDuration;
+/** The duration(ms) between first video key frame received and connection start, 0 if not valid
+ */
+@property(assign, nonatomic) NSInteger firstVideoKeyFramePacketDuration;
+/** Video packet number before first video key frame received, 0 if not valid
+ */
+@property(assign, nonatomic) NSInteger packetsBeforeFirstKeyFramePacket;
+/**
+ * The packet loss rate of sender(broadcaster).
+ */
+@property(assign, nonatomic) NSInteger txPacketLossRate;
+/**
+ * The packet loss rate of receiver(audience).
+ */
+@property(assign, nonatomic) NSInteger rxPacketLossRate;
+
+@end
+/** Properties of the video encoder configuration.
+*/
+__attribute__((visibility("default"))) @interface AgoraAdvancedVideoOptions : NSObject
+/**
+* The video encoder encodingPreference hard or soft
+*/
+@property(assign, nonatomic) AgoraEncodingPreference encodingPreference;
+
+/** The video compression preference. */
+@property(assign, nonatomic) AgoraCompressionPreference compressionPreference;
+
+@end
+
+__attribute__((visibility("default"))) @interface AgoraVideoCodecCapLevels : NSObject
+
+@property(assign, nonatomic) AgoraVideoCodecCapabilityLevel hwDecodingLevel;
+@property(assign, nonatomic) AgoraVideoCodecCapabilityLevel swDecodingLevel;
+
+@end
+
+/**
+ * The codec support information.
+*/
+__attribute__((visibility("default"))) @interface AgoraVideoCodecCapInfo : NSObject
+
+/** The codec type. */
+@property(assign, nonatomic) AgoraVideoCodecType codecType;
+/** The codec type mask. bit 1 Hardware decoder support flag, bit 2: Hardware encoder support flag,
+ * bit 3: Software decoder support flag, bit 4: Software encoder support flag */
+@property(assign, nonatomic) NSUInteger codecCapMask;
+
+/** The codec capability level, estimated based on the device hardware.*/
+@property(strong, nonatomic) AgoraVideoCodecCapLevels *_Nonnull codecCapLevels;
+
+@end
+/** Properties of the video encoder configuration.
+ */
+__attribute__((visibility("default"))) @interface AgoraVideoEncoderConfiguration : NSObject
+/** Video resolution that can be set manually or by choosing from one of the following
+ enumerations, the default value is 960x540:
+
+ - AgoraVideoDimension120x120
+ - AgoraVideoDimension160x120
+ - AgoraVideoDimension180x180
+ - AgoraVideoDimension240x180
+ - AgoraVideoDimension320x180
+ - AgoraVideoDimension240x240
+ - AgoraVideoDimension320x240
+ - AgoraVideoDimension424x240
+ - AgoraVideoDimension360x360
+ - AgoraVideoDimension480x360
+ - AgoraVideoDimension640x360
+ - AgoraVideoDimension480x480
+ - AgoraVideoDimension640x480
+ - AgoraVideoDimension840x480
+ - AgoraVideoDimension960x540
+ - AgoraVideoDimension960x720
+ - AgoraVideoDimension1280x720
+ - AgoraVideoDimension1920x1080
+ - AgoraVideoDimension2540x1440
+ - AgoraVideoDimension3840x2160
+
+ @note Whether 720p can be supported depends on the device. If the device cannot support 720p,
+ the frame rate will be lower than the one listed in the table. Agora optimizes the video in
+ lower-end devices. Contact mailto:support@agora.io for special requirements.
+ */
+@property(assign, nonatomic) CGSize dimensions;
+
+/** Codec type. See \ref AgoraVideoCodecType.
+ */
+@property(assign, nonatomic) AgoraVideoCodecType codecType;
+
+/** Frame rate of the video: AgoraVideoFrameRate
+ */
+@property(assign, nonatomic) AgoraVideoFrameRate frameRate;
+
+/** Bitrate of the video:
+
+ Refer to AgoraVideoProfile and set your desired bitrate. If the bitrate you set is beyond the
+ proper range, the SDK will automatically adjust it to a value within the range. You can also choose
+ from the following options:
+
+ - AgoraVideoBitrateStandard:
+
+ - The standard bitrate in [setVideoEncoderConfiguration]([AgoraRtcEngineKit
+ setVideoEncoderConfiguration:]). - (Recommended) In a live broadcast, Agora recommends setting a
+ larger bitrate to improve the video quality. When you choose AgoraVideoBitrateStandard, the bitrate
+ value doubles in a live broadcast mode, and remains the same as in AgoraVideoProfile in a
+ communication mode.
+
+ - AgoraVideoBitrateCompatible:
+
+ - The compatible bitrate in [setVideoEncoderConfiguration]([AgoraRtcEngineKit
+ setVideoEncoderConfiguration:]). - The bitrate in both the live broadcast and communication modes
+ remain the same as in AgoraVideoProfile.
+ */
+@property(assign, nonatomic) NSInteger bitrate;
+
+@property(assign, nonatomic) NSInteger minBitrate;
+
+/** Video orientation mode of the video: AgoraVideoOutputOrientationMode.
+ */
+@property(assign, nonatomic) AgoraVideoOutputOrientationMode orientationMode;
+
+/** Video mirror mode of the video: AgoraVideoMirrorMode.
+ */
+@property(assign, nonatomic) AgoraVideoMirrorMode mirrorMode;
+
+/** The video encoding degradation preference under limited bandwidth.
+
+AgoraDegradationPreference:
+
+* AgoraDegradationMaintainQuality(0): (Default) Degrades the frame rate to guarantee the video quality.
+* AgoraDegradationMaintainFramerate(1): Degrades the video quality to guarantee the frame rate.
+*/
+@property (assign, nonatomic) AgoraDegradationPreference degradationPreference;
+
+/** The video hardwareEncoding. */
+@property (strong, nonatomic) AgoraAdvancedVideoOptions *_Nullable advancedVideoOptions;
+
+/** Initializes and returns a newly allocated AgoraVideoEncoderConfiguration object with the
+ specified video resolution.
+
+ @param size Video resolution
+ @param frameRate Video frame rate
+ @param bitrate Video bitrate
+ @param orientationMode AgoraVideoOutputOrientationMode
+ @param mirrorMode AgoraVideoMirrorMode
+ @return An initialized AgoraVideoEncoderConfiguration object
+ */
+- (instancetype _Nonnull)initWithSize:(CGSize)size
+ frameRate:(AgoraVideoFrameRate)frameRate
+ bitrate:(NSInteger)bitrate
+ orientationMode:(AgoraVideoOutputOrientationMode)orientationMode
+ mirrorMode:(AgoraVideoMirrorMode)mirrorMode NS_SWIFT_NAME(init(size:frameRate:bitrate:orientationMode:mirrorMode:));
+
+/** Initializes and returns a newly allocated AgoraVideoEncoderConfiguration object with the
+ specified video width and height.
+
+ @param width Width of the video
+ @param height Height of the video
+ @param frameRate Video frame rate
+ @param bitrate Video bitrate
+ @param orientationMode AgoraVideoOutputOrientationMode
+ @param mirrorMode AgoraVideoMirrorMode
+ @return An initialized AgoraVideoEncoderConfiguration object
+ */
+- (instancetype _Nonnull)initWithWidth:(NSInteger)width
+ height:(NSInteger)height
+ frameRate:(AgoraVideoFrameRate)frameRate
+ bitrate:(NSInteger)bitrate
+ orientationMode:(AgoraVideoOutputOrientationMode)orientationMode
+ mirrorMode:(AgoraVideoMirrorMode)mirrorMode NS_SWIFT_NAME(init(width:height:frameRate:bitrate:orientationMode:mirrorMode:));
+@end
+
+/** A class for providing user-specific audio/video transcoding settings.
+ */
+__attribute__((visibility("default"))) @interface AgoraLiveTranscodingUser : NSObject
+/** User ID.
+ */
+@property(assign, nonatomic) NSUInteger uid;
+/** Position and size of the video frame.
+ */
+@property(assign, nonatomic) CGRect rect;
+/** Video frame layer number, in the range of 1 to 100.
+
+ * 1: The video frame image is in the lowest layer (default)
+ * 100: The video frame image is in the highest layer
+ */
+@property(assign, nonatomic) NSInteger zOrder;
+/** Transparency of the video frame, between 0 and 1.0:
+
+ * 0: Completely transparent
+ * 1.0: Opaque (default)
+ */
+@property(assign, nonatomic) double alpha;
+/** The audio channel of the sound. The default value is 0:
+
+ * 0: (default) Supports dual channels at most, depending on the upstream of the broadcaster.
+ * 1: The audio stream of the broadcaster is in the FL audio channel. If the upstream of the
+ broadcaster uses dual-sound channel, only the left-sound channel will be used for streaming. * 2:
+ The audio stream of the broadcaster is in the FC audio channel. If the upstream of the broadcaster
+ uses dual-sound channel, only the left-sound channel will be used for streaming. * 3: The audio
+ stream of the broadcaster is in the FR audio channel. If the upstream of the broadcaster uses
+ dual-sound channel, only the left-sound channel will be used for streaming. * 4: The audio stream
+ of the broadcaster is in the BL audio channel. If the upstream of the broadcaster uses dual-sound
+ channel, only the left-sound channel will be used for streaming. * 5: The audio stream of the
+ broadcaster is in the BR audio channel. If the upstream of the broadcaster uses dual-sound channel,
+ only the left-sound channel will be used for streaming.
+ */
+@property(assign, nonatomic) NSInteger audioChannel;
+@end
+
+/** The configuration for advanced features of the RTMP or RTMPS streaming with transcoding.
+ */
+__attribute__((visibility("default"))) @interface AgoraLiveStreamAdvancedFeature : NSObject
+
+/** The name of the advanced feature, including the following:
+
+ - LBHQ: The advanced feature for high-quality video with a lower bitrate.
+ - VEO: The advanced feature for the optimized video encoder.
+*/
+@property(copy, nonatomic) NSString* _Nullable featureName;
+
+/** Whether to enable the advanced feature:
+
+ - YES: Enable the advanced feature.
+ - NO: (Default) Disable the advanced feature.
+ */
+@property(assign, nonatomic) BOOL opened;
+@end
+
+/** Watermark image properties.
+ */
+__attribute__((visibility("default"))) @interface AgoraImage : NSObject
+/** URL address of the watermark on the broadcasting video
+ */
+@property(strong, nonatomic) NSURL *_Nonnull url;
+/** Position and size of the watermark on the broadcasting video in CGRect
+ */
+@property(assign, nonatomic) CGRect rect;
+/**
+ * Order attribute for an ordering of overlapping two-dimensional objects.
+*/
+@property (assign, nonatomic) NSInteger zOrder;
+/** The transparency level of the image.
+
+ The value ranges between 0.0 and 1.0:
+
+ * 0.0: Completely transparent.
+ * 1.0: (Default) Opaque.
+ */
+@property(assign, nonatomic) double alpha;
+@end
+
+/** The options of the watermark image to be added.
+ */
+__attribute__((visibility("default"))) @interface WatermarkOptions : NSObject
+/** Sets whether or not the watermark image is visible in the local video preview:
+
+ - YES: (Default) The watermark image is visible in preview.
+ - NO: The watermark image is not visible in preview.
+ */
+@property(assign, nonatomic) BOOL visibleInPreview;
+/** The watermark position in landscape mode of *Rotate the Video*. This parameter contains the following members:
+
+ - `x`: The horizontal offset of the watermark from the top-left corner.
+ - `y`: The vertical offset of the watermark from the top-left corner.
+ - `width`: The width (pixel) of the watermark region.
+ - `height`: The height (pixel) of the watermark region.
+ */
+@property(assign, nonatomic) CGRect positionInLandscapeMode;
+/** The watermark position in portrait mode of *Rotate the Video*. This parameter contains the following members:
+
+ - `x`: The horizontal offset of the watermark from the top-left corner.
+ - `y`: The vertical offset of the watermark from the top-left corner.
+ - `width`: The width (pixel) of the watermark region.
+ - `height`: The height (pixel) of the watermark region.
+ */
+@property(assign, nonatomic) CGRect positionInPortraitMode;
+@end
+
+/** A class for managing CDN transcoding.
+ */
+__attribute__((visibility("default"))) @interface AgoraLiveTranscoding : NSObject
+/** The size of the video (width and height in pixels).
+
+- When pushing video streams to the CDN, note the following:
+
+ - The value range of the width is [64,1920]. If the value is less than 64,
+ Agora server automatically adjusts it to 64; if the value is greater than
+ 1920, Agora server automatically adjusts it to 1920.
+ - The value range of the height is [64,1080]. If the value is less than 64,
+ Agora server automatically adjusts it to 64; if the value is greater than
+ 1080, Agora server automatically adjusts it to 1080.
+
+- When pushing audio streams to the CDN, set the width and height as 0.
+ */
+@property(assign, nonatomic) CGSize size;
+/** Bitrate of the CDN live output video stream.
+
+The default value is 400 Kbps.
+
+Set this parameter according to the Video Bitrate Table. If you set a bitrate beyond the proper range, the SDK automatically adapts it to a value within the range.
+ */
+@property(assign, nonatomic) NSInteger videoBitrate;
+/** Frame rate of the CDN live output video stream.
+
+The default value is 15 fps, and the value range is (0,30].
+
+ @note The Agora server adjusts any value over 30 to 30.
+ */
+@property(assign, nonatomic) NSInteger videoFramerate;
+/** Latency mode. **DEPRECATED** from v2.8.0
+
+ * YES: Low latency with unassured quality.
+ * NO:(Default)High latency with assured quality.
+ */
+@property(assign, nonatomic) BOOL lowLatency;
+/** Video GOP in frames. The default value is 30 fps. */
+@property(assign, nonatomic) NSInteger videoGop;
+/** Video codec profile type
+
+Set it as 66, 77, or 100 (default), see [AgoraVideoCodecProfileType](AgoraVideoCodecProfileType).
+
+If you set this parameter to other values, Agora adjusts it to the default value of 100.
+ */
+@property(assign, nonatomic) AgoraVideoCodecProfileType videoCodecProfile;
+
+/** The video codec type of the output video stream. See AgoraVideoCodecTypeForStream.
+
+ @since v3.2.0
+ */
+@property(assign, nonatomic) AgoraVideoCodecTypeForStream videoCodecType;
+
+/** An AgoraLiveTranscodingUser object managing the user layout configuration in the CDN live stream. Agora supports a maximum of 17 transcoding users in a CDN live stream channel. See AgoraLiveTranscodingUser.
+ */
+@property(copy, nonatomic) NSArray* _Nullable transcodingUsers;
+
+/** Reserved property. Extra user-defined information to send SEI for the H.264/H.265 video stream to the CDN live client. Maximum length: 4096 bytes. For more information on SEI, see [SEI-related questions](https://docs.agora.io/en/faq/sei).
+ */
+@property(copy, nonatomic) NSString* _Nullable transcodingExtraInfo;
+
+/**
+ * add few watermarks
+ */
+@property(copy, nonatomic) NSArray* _Nullable watermarkArray;
+
+/**
+ * add few backgroundImage
+ */
+@property(copy, nonatomic) NSArray* _Nullable backgroundImageArray;
+
+/** The background color in RGB hex.
+
+Value only. Do not include a preceding #. For example, 0xFFB6C1 (light pink). The default value is 0x000000 (black).
+
+COLOR_CLASS is a general name for the type:
+
+* iOS: UIColor
+* macOS: NSColor
+ */
+@property(strong, nonatomic) COLOR_CLASS* _Nullable backgroundColor;
+
+/** Self-defined audio sample rate: AgoraAudioSampleRateType.
+ */
+@property(assign, nonatomic) AgoraAudioSampleRateType audioSampleRate;
+/** Bitrate (Kbps) of the CDN live audio output stream. The default value is 48, and the highest value is 128.
+ */
+@property(assign, nonatomic) NSInteger audioBitrate;
+/** The number of audio channels for the CDN live stream.
+
+ Agora recommends choosing 1 (mono), or 2 (stereo) audio channels. Special players are required if you choose 3, 4, or 5.
+
+ * 1: (Default) Mono
+ * 2: Stereo
+ * 3: Three audio channels
+ * 4: Four audio channels
+ * 5: Five audio channels
+ */
+@property(assign, nonatomic) NSInteger audioChannels;
+/**
+ Audio codec profile. See AgoraAudioCodecProfileType.
+
+ The default value is AgoraAudioCodecProfileLCAAC(0).
+ */
+@property(assign, nonatomic) AgoraAudioCodecProfileType audioCodecProfile;
+
+/** Creates a default transcoding object.
+
+ @return Default AgoraLiveTranscoding object.
+ */
++ (AgoraLiveTranscoding* _Nonnull)defaultTranscoding NS_SWIFT_NAME(default());
+
+/** Adds a user displaying the video in CDN live.
+
+ @param user The transcoding user. See AgoraLiveTranscodingUser.
+
+ @return - 0: Success.
+ - < 0: Failure.
+ */
+- (int)addUser:(AgoraLiveTranscodingUser* _Nonnull)user NS_SWIFT_NAME(add(_:));
+
+/** Removes a user from CDN live.
+
+ @param uid The user ID of the user to remove from CDN live.
+
+ @return - 0: Success.
+ - < 0: Failure.
+ */
+- (int)removeUser:(NSUInteger)uid NS_SWIFT_NAME(removeUser(_:));
+
+/** Enables/Disables advanced features of the RTMP or RTMPS streaming with transcoding.
+
+ @param featureName The name of the advanced feature, including the following:
+ LBHQ: The advanced feature for high-quality video with a lower bitrate.
+ VEO: The advanced feature for the optimized video encoder.
+ @param opened Whether to enable the advanced feature:
+ YES: Enable the advanced feature.
+ NO: (Default) Disable the advanced feature.
+ */
+- (void)setAdvancedFeatures:(NSString* _Nonnull)featureName opened:(BOOL)opened NS_SWIFT_NAME(setAdvancedFeatures(_:opened:));
+
+/** Checks whether advanced features of the RTMP or RTMPS streaming with transcoding are enabled.
+ @return The name of each advanced feature and whether the advanced feature is enabled.
+ */
+- (NSArray* _Nullable)getAdvancedFeatures NS_SWIFT_NAME(getAdvancedFeatures());
+
+@end
+
+/** Live broadcast import stream configuration.
+ */
+__attribute__((visibility("default"))) @interface AgoraLiveInjectStreamConfig : NSObject
+/** Size of the stream to be imported into the live broadcast. The default value is 0; same
+ * size as the original stream.
+ */
+@property(assign, nonatomic) CGSize size;
+/** Video GOP of the stream to be added into the broadcast. The default value is 30.
+ */
+@property(assign, nonatomic) NSInteger videoGop;
+/** Video frame rate of the stream to be added into the broadcast. The default value is 15 fps.
+ */
+@property(assign, nonatomic) NSInteger videoFramerate;
+/** Video bitrate of the stream to be added into the broadcast. The default value is 400 Kbps.
+ */
+@property(assign, nonatomic) NSInteger videoBitrate;
+
+/** Audio sampling rate of the stream to be added into the broadcast. The default value is 48000.
+ */
+@property(assign, nonatomic) AgoraAudioSampleRateType audioSampleRate;
+/** Audio bitrate of the stream to be added into the broadcast. The default value is 48 Kbps.
+ */
+@property(assign, nonatomic) NSInteger audioBitrate;
+/** Audio channels to be added into the broadcast. The default value is 1.
+ */
+@property(assign, nonatomic) NSInteger audioChannels;
+
+/** Create a default stream config
+
+ @return default stream config
+ */
++ (AgoraLiveInjectStreamConfig *_Nonnull)defaultConfig NS_SWIFT_NAME(defaultConfig());
+@end
+
+ __deprecated
+
+ /** AgoraRtcVideoCompositingRegion array.
+ */
+ __attribute__((visibility("default"))) @interface AgoraRtcVideoCompositingRegion
+ : NSObject
+ /** User ID of the user with the video to be displayed in the region.
+ */
+ @property(assign, nonatomic) NSUInteger uid;
+/** Horizontal position of the region on the screen (0.0 to 1.0).
+ */
+@property(assign, nonatomic) CGFloat x;
+/** Vertical position of the region on the screen (0.0 to 1.0).
+ */
+@property(assign, nonatomic) CGFloat y;
+/** Actual width of the region (0.0 to 1.0).
+ */
+@property(assign, nonatomic) CGFloat width;
+/** Actual height of the region (0.0 to 1.0).
+ */
+@property(assign, nonatomic) CGFloat height;
+/** 0 means the region is at the bottom, and 100 means the region is at the top.
+ */
+@property(assign, nonatomic) NSInteger zOrder;
+/** 0 means the region is transparent, and 1 means the region is opaque. The default value is 1.0.
+ */
+@property(assign, nonatomic) CGFloat alpha;
+/** Render mode: AgoraVideoRenderMode
+ */
+@property(assign, nonatomic) AgoraVideoRenderMode renderMode;
+@end
+
+ __deprecated
+ /** Rtc video compositing layout.
+ */
+ __attribute__((visibility("default"))) @interface AgoraRtcVideoCompositingLayout
+ : NSObject
+ /** Width of the entire canvas (display window or screen).
+ */
+ @property(assign, nonatomic) NSInteger canvasWidth;
+/** Height of the entire canvas (display window or screen).
+ */
+@property(assign, nonatomic) NSInteger canvasHeight;
+/** Enter any of the 6-digit symbols defined in RGB. For example, "#c0c0c0"
+ */
+@property(copy, nonatomic) NSString *_Nullable backgroundColor;
+/** AgoraRtcVideoCompositingRegion array.
+ */
+@property(copy, nonatomic) NSArray *_Nullable regions;
+/** Application defined data.
+ */
+@property(copy, nonatomic) NSString *_Nullable appData;
+@end
+
+ /**
+ @deprecated
+
+ Sets whether the current host is the RTMP stream owner.
+ */
+ __deprecated __attribute__((visibility("default"))) @interface AgoraPublisherConfiguration
+ : NSObject
+ /**
+ - YES: The current host is the RTMP stream owner and the push-stream configuration is enabled
+ (default). - NO: The current host is not the RTMP stream owner and the push-stream
+ configuration is disabled.
+ */
+ @property(assign, nonatomic) BOOL owner;
+
+/** Width of the output data stream set for CDN Live. 360 is the default value
+ */
+@property(assign, nonatomic) NSInteger width;
+/** Height of the output data stream set for CDN Live. 640 is the default value
+ */
+@property(assign, nonatomic) NSInteger height;
+/** Frame rate of the output data stream set for CDN Live. 15 fps is the default value
+ */
+@property(assign, nonatomic) NSInteger framerate;
+/** Bitrate of the output data stream set for CDN Live. 500 kbit/s is the default value
+ */
+@property(assign, nonatomic) NSInteger bitrate;
+/** Audio sample rate of the output data stream set for CDN Live. The default value is 48000.
+ */
+@property(assign, nonatomic) NSInteger audiosamplerate;
+/** Audio bitrate of the output data stream set for CDN Live. The default value is 48.
+ */
+@property(assign, nonatomic) NSInteger audiobitrate;
+/** Audio channels of the output data stream set for CDN Live. The default value is 1.
+ */
+@property(assign, nonatomic) NSInteger audiochannels;
+
+/**
+
+* 0: Tile Horizontally
+* 1: Layered Windows
+* 2: Tile Vertically
+ */
+@property(assign, nonatomic) NSInteger defaultLayout;
+/** Video stream lifecycle of CDN Live: AgoraRtmpStreamLifeCycle
+ */
+@property(assign, nonatomic) AgoraRtmpStreamLifeCycle lifeCycle;
+
+/** Width of the stream to be injected. Set it as 0.
+ */
+@property(assign, nonatomic) NSInteger injectStreamWidth;
+
+/** Height of the stream to be injected. Set it as 0.
+ */
+@property(assign, nonatomic) NSInteger injectStreamHeight;
+
+/** Address of the stream to be injected to the channel.
+ */
+@property(copy, nonatomic) NSString *_Nullable injectStreamUrl;
+
+/** The push-stream address for the picture-in-picture layouts. The default value is *NULL*.
+ */
+@property(copy, nonatomic) NSString *_Nullable publishUrl;
+
+/** The push-stream address of the original stream which does not require picture-blending. The
+ * default value is NULL.
+ */
+@property(copy, nonatomic) NSString *_Nullable rawStreamUrl;
+
+/** Reserved field. The default value is NULL.
+ */
+@property(copy, nonatomic) NSString *_Nullable extraInfo;
+
+/** Check if configuration is validate
+ */
+- (BOOL)validate NS_SWIFT_NAME(validate());
+
+- (NSString * _Nullable)toJsonString NS_SWIFT_NAME(toJsonString());
+@end
+
+#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC))
+
+/** AgoraRtcDeviceInfo array.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcDeviceInfo : NSObject
+@property (assign, nonatomic) int __deprecated index;
+
+/** AgoraMediaDeviceType
+ */
+@property(assign, nonatomic) AgoraMediaDeviceType type;
+
+/** Device ID.
+ */
+@property(copy, nonatomic) NSString *_Nullable deviceId;
+
+/** Device name.
+ */
+@property(copy, nonatomic) NSString *_Nullable deviceName;
+@end
+#endif
+
+/** Properties of the AgoraVideoFrame object.
+ */
+__attribute__((visibility("default"))) @interface AgoraVideoFrame : NSObject
+/** Video format:
+
+ * - 1: I420
+ * - 2: BGRA
+ * - 3: NV21
+ * - 4: RGBA
+ * - 5: IMC2
+ * - 7: ARGB
+ * - 8: NV12
+ * - 12: iOS texture (CVPixelBufferRef)
+ * - 13: Still Image (UIImage for iPhone, NSImage for Mac)
+ */
+@property(assign, nonatomic) NSInteger format;
+
+/** Timestamp of the incoming video frame (ms). An incorrect timestamp will result in frame loss or
+ * unsynchronized audio and video.
+ */
+@property(assign, nonatomic) CMTime time; // Time for this frame.
+
+/**
+ @deprecated Use strideInPixels instead.
+ */
+@property(assign, nonatomic) int stride DEPRECATED_MSG_ATTRIBUTE("use strideInPixels instead");
+
+/** Line spacing of the incoming video frame, which must be in pixels instead of bytes. For
+ * textures, it is the width of the texture.
+ */
+@property(assign, nonatomic) int strideInPixels; // Number of pixels between two consecutive rows.
+ // Note: in pixel, not byte. Not used for iOS
+ // textures.
+
+/** Height of the incoming video frame.
+ */
+@property(assign, nonatomic) int height; // Number of rows of pixels. Not used for iOS textures.
+
+/** CVPixelBuffer
+ */
+@property(assign, nonatomic) CVPixelBufferRef _Nullable textureBuf;
+
+/** Still Image (UIImage for iPhone, NSImage for Mac)
+ */
+@property(strong, nonatomic) IMAGE_CLASS * _Nullable image;
+
+/** Raw data buffer.
+ */
+@property(strong, nonatomic) NSData *_Nullable dataBuf; // Raw data buffer. Not used for iOS textures.
+
+/**
+ * Indicates the alpha channel of current frame, which is consistent with the dimension of the video frame.
+ * The value range of each pixel is [0,255], where 0 represents the background; 255 represents the foreground.
+ * The default value is nill.
+ */
+@property(strong, nonatomic) NSData *_Nullable alphaBuf;
+
+/** (Optional) Specifies the number of pixels trimmed from the left, which is set as 0 by default.
+ */
+@property(assign, nonatomic) int cropLeft; // Number of pixels to crop on the left boundary.
+/** (Optional) Specifies the number of pixels trimmed from the top, which is set as 0 by default.
+ */
+@property(assign, nonatomic) int cropTop; // Number of pixels to crop on the top boundary.
+/** (Optional) Specifies the number of pixels trimmed from the right, which is set as 0 by default.
+ */
+@property(assign, nonatomic) int cropRight; // Number of pixels to crop on the right boundary.
+/** (Optional) Specifies the number of pixels trimmed from the bottom, which is set as 0 by default.
+ */
+@property(assign, nonatomic) int cropBottom; // Number of pixels to crop on the bottom boundary.
+/** (Optional) Specifies whether to rotate the incoming video group. Optional values: 0, 90, 180, or
+ * 270 clockwise. Set as 0 by default.
+ */
+@property(assign, nonatomic) int rotation; // 0, 90, 180, 270. See document for rotation calculation.
+/* Note
+ * 1. strideInPixels
+ * Stride is in pixels, not bytes
+ * 2. About the frame width and height
+ * No field is defined for the width. However, it can be deduced by:
+ * croppedWidth = (strideInPixels - cropLeft - cropRight)
+ * And
+ * croppedHeight = (height - cropTop - cropBottom)
+ * 3. About crop
+ * _________________________________________________________________.....
+ * | ^ | ^
+ * | | | |
+ * | cropTop | |
+ * | | | |
+ * | v | |
+ * | ________________________________ | |
+ * | | | | |
+ * | | | | |
+ * |<-- cropLeft -->| valid region |<- cropRight ->|
+ * | | | | height
+ * | | | |
+ * | |_____________________________ | | |
+ * | ^ | |
+ * | | | |
+ * | cropBottom | |
+ * | | | |
+ * | v | v
+ * _________________________________________________________________......
+ * | |
+ * |<---------------- strideInPixels ----------------------------->|
+ *
+ * If your buffer contains garbage data, you can crop them. For example, the frame size is
+ * 360 x 640, often the buffer stride is 368, that is, there extra 8 pixels on the
+ * right are for padding, and should be removed. In this case, you can set:
+ * strideInPixels = 368;
+ * height = 640;
+ * cropRight = 8;
+ * // cropLeft, cropTop, cropBottom are set to a default of 0
+ */
+
+/** If data format is BGRA or RGBA and alphaBuf is nill, it is required to call fillAlphaData to fill alphaBuf.
+ */
+- (void)fillAlphaData;
+@end
+
+__attribute__((visibility("default"))) @interface AgoraLogConfig: NSObject
+/** The absolute path of log files.
+
+ Ensure that the directory for the log
+ files exists and is writable. The default file path is as follows:
+
+ - iOS: `App Sandbox/Library/caches/agorasdk.log`
+ - macOS:
+ - Sandbox enabled: `App Sandbox/Library/Logs/agorasdk.log`, such as
+ `/Users//Library/Containers//Data/Library/Logs/agorasdk.log`
+ - Sandbox disabled: `�Library/Logs/agorasdk.log`
+ */
+@property (copy, nonatomic) NSString * _Nullable filePath;
+/** The size (KB) of a log file.
+
+ The default value is 1024 KB. If you set
+ this parameter to 1024 KB, the SDK outputs at most 5 MB log files; if
+ you set it to less than 1024 KB, the setting is invalid, and the maximum
+ size of a log file is still 1024 KB.
+ */
+@property (assign, nonatomic) NSInteger fileSizeInKB;
+/** The output log level of the SDK. See details in AgoraLogLevel.
+
+ For example, if you set the log level to `AgoraLogLevelWarn`, the SDK outputs the logs
+ within levels `AgoraLogLevelFatal`, `AgoraLogLevelError`, and `AgoraLogLevelWarn`.
+ */
+@property (assign, nonatomic) AgoraLogLevel level;
+@end
+
+/**
+ * The config of AgoraRtcEngine.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcEngineConfig: NSObject
+
+ /**
+ * The App ID issued to the developers by Agora. Apply for a new one from Agora if it is missing from
+ * your kit.
+ */
+ @property (copy, nonatomic) NSString * _Nullable appId;
+
+/**
+ * The channel profile. See #AgoraChannelProfile.
+ */
+ @property (assign, nonatomic) AgoraChannelProfile channelProfile;
+
+ /**
+ * The license used for verification when connectting channel. Charge according to the license
+ */
+ @property (copy, nonatomic) NSString * _Nullable license;
+
+ /**
+ * The audio application scenario. See #AgoraAudioScenario.
+ *
+ * @note Agora recommends the following scenarios:
+ * - `AgoraAudioScenarioDefault = 0`
+ * - `AgoraAudioScenarioGameStreaming = 3`
+ */
+ @property (assign, nonatomic) AgoraAudioScenario audioScenario;
+ /**
+ * The region for connection. This advanced feature applies to scenarios that
+ * have regional restrictions.
+ *
+ * For the regions that Agora supports, see \ref AgoraAreaCodeType.
+ *
+ * After specifying the region, the SDK connects to the Agora servers within
+ * that region.
+ */
+ @property (assign, nonatomic) AgoraAreaCodeType areaCode;
+ @property (strong, nonatomic) AgoraLogConfig * _Nullable logConfig;
+ /**
+ * Thread priority for SDK common threads
+ *
+ * See \ref AgoraThreadPriorityType.
+ */
+ @property (assign, nonatomic) AgoraThreadPriorityType threadPriority;
+ @property (weak, nonatomic) id _Nullable eventDelegate;
+ /**
+ * Determines whether to enable domain limit.
+ * - `true`: only connect to servers that already parsed by DNS
+ * - `false`: (Default) connect to servers with no limit
+ */
+ @property (assign, nonatomic) BOOL domainLimit;
+@end
+
+/**
+ * The class of AgoraAudioFrame.
+ */
+__attribute__((visibility("default"))) @interface AgoraAudioFrame : NSObject
+/** The number of samples per channel.
+ */
+@property(assign, nonatomic) NSInteger samplesPerChannel;
+/** The number of bytes per audio sample. For example, each PCM audio sample
+ usually takes up 16 bits (2 bytes).
+ */
+@property(assign, nonatomic) NSInteger bytesPerSample;
+/** The number of audio channels. If the channel uses stereo, the data is
+ interleaved.
+
+- 1: Mono.
+- 2: Stereo.
+ */
+@property(assign, nonatomic) NSInteger channels;
+/** The sample rate.
+ */
+@property(assign, nonatomic) NSInteger samplesPerSec;
+/** The buffer of the sample audio data. When the audio frame uses a stereo
+ channel, the data buffer is interleaved. The size of the data buffer is as
+ follows: `buffer` = `samplesPerChannel` × `channels` × `bytesPerSample`.
+ */
+@property(assign, nonatomic) void* _Nullable buffer;
+/** The timestamp of the external audio frame. You can use this parameter for
+ the following purposes:
+
+- Restore the order of the captured audio frame.
+- Synchronize audio and video frames in video-related scenarios, including
+where external video sources are used.
+ */
+@property(assign, nonatomic) int64_t renderTimeMs;
+/** Reserved for future use.
+ */
+@property(assign, nonatomic) NSInteger avSyncType;
+@end
+
+/** The AgoraAudioParams interface
+ You can pass the `AgoraAudioParams` object in the return value of the following
+ callbacks to set the audio data format for the corresponding callbacks:
+
+ - [getRecordAudioParams]([AgoraAudioFrameDelegate getRecordAudioParams]):
+ Sets the audio recording format for the
+ [onRecordAudioFrame]([AgoraAudioFrameDelegate onRecordAudioFrame:])
+ callback.
+ - [getPlaybackAudioParams]([AgoraAudioFrameDelegate getPlaybackAudioParams]):
+ Sets the audio playback format for the
+ [onPlaybackAudioFrame]([AgoraAudioFrameDelegate onPlaybackAudioFrame:])
+ callback.
+ - [getMixedAudioParams]([AgoraAudioFrameDelegate getMixedAudioParams]):
+ Sets the audio mixing format for the
+ [onMixedAudioFrame]([AgoraAudioFrameDelegate onMixedAudioFrame:]) callback.
+
+ @note The SDK calculates the sample interval according to the
+ `samplesPerCall`, `sampleRate`, and `channel` values in the
+ `AgoraAudioParams` interface and triggers the following callbacks at the
+ calculated sample interval:
+
+ - [onRecordAudioFrame]([AgoraAudioFrameDelegate onRecordAudioFrame:])
+ - [onPlaybackAudioFrame]([AgoraAudioFrameDelegate onPlaybackAudioFrame:])
+ - [onMixedAudioFrame]([AgoraAudioFrameDelegate onMixedAudioFrame:])
+
+ Sample interval (seconds) = `samplesPerCall`/(`sampleRate` × `channel`).
+ Ensure that the value of sample interval is equal to or greater than 0.01.
+ */
+__attribute__((visibility("default"))) @interface AgoraAudioParams : NSObject
+
+/** The audio sample rate (Hz), which can be set as one of the following values:
+
+ - `8000`
+ - `16000` (Default)
+ - `32000`
+ - `44100 `
+ - `48000`
+ */
+@property (assign, nonatomic) NSInteger sampleRate;
+
+/* The number of audio channels, which can be set as either of the following values:
+
+ - `1`: Mono (Default)
+ - `2`: Stereo
+ */
+@property (assign, nonatomic) NSInteger channel;
+
+/* The use mode of the audio data. See AgoraAudioRawFrameOperationMode.
+ */
+@property (assign, nonatomic) AgoraAudioRawFrameOperationMode mode;
+
+/** The number of samples. For example, set it as 1024 for RTMP or RTMPS
+ streaming.
+ */
+@property (assign, nonatomic) NSInteger samplesPerCall;
+
+@end
+
+/**
+ * The class of AgoraEncodedAudioFrameInfo.
+ */
+__attribute__((visibility("default"))) @interface AgoraEncodedAudioFrameInfo: NSObject
+ @property (assign, nonatomic) NSInteger samplesPerChannel;
+ @property (assign, nonatomic) NSInteger channels;
+ @property (assign, nonatomic) NSInteger samplesPerSec;
+ @property (assign, nonatomic) AgoraAudioCodecType codecType;
+@end
+
+/**
+ * The collections of uplink network info.
+ */
+__attribute__((visibility("default"))) @interface AgoraUplinkNetworkInfo : NSObject
+/**
+* The target video encoder bitrate bps.
+*/
+@property(nonatomic, assign) int videoEncoderTargetBitrateBps;
+@end
+
+/**
+ * The collections of downlink network info.
+ */
+__attribute__((visibility("default"))) @interface AgoraDownlinkNetworkInfo : NSObject
+/**
+* The lastmile buffer delay time in ms.
+*/
+@property(nonatomic, assign) int lastmileBufferDelayTimeMs;
+/**
+* The downlink bandwidth estimation bitrate bps.
+*/
+@property(nonatomic, assign) int bandwidthEstimationBps;
+@end
+
+/**
+ * The leave channel options.
+ */
+__attribute__((visibility("default"))) @interface AgoraLeaveChannelOptions : NSObject
+/**
+ * Determines whether to stop playing and mixing the music file when leave channel.
+ * - true: (Default) Stop playing and mixing the music file.
+ * - false: Do not stop playing and mixing the music file.
+ */
+@property(nonatomic, assign) BOOL stopAudioMixing;
+
+/**
+ * Determines whether to stop all music effects when leave channel.
+ * - true: (Default) Stop all music effects.
+ * - false: Do not stop the music effect.
+ */
+@property(nonatomic, assign) BOOL stopAllEffect;
+
+/**
+ * Determines whether to stop microphone recording when leave channel.
+ * - true: (Default) Stop microphone recording.
+ * - false: Do not stop microphone recording.
+ */
+@property(nonatomic, assign) BOOL stopMicrophoneRecording;
+
+@end
+
+__attribute__((visibility("default"))) @interface AgoraOutputVideoFrame : NSObject
+
+/** Video format:
+ * - 1: I420
+ * - 2: BGRA
+ * - 3: NV21
+ * - 4: RGBA
+ * - 5: IMC2
+ * - 7: ARGB
+ * - 8: NV12
+ * - 12: iOS texture NV12 (CVPixelBufferRef)
+ * - 13: iOS texture I420 (CVPixelBufferRef)
+ * - 14: iOS texture BGRA (CVPixelBufferRef)
+ */
+@property (nonatomic, assign) NSInteger type;
+/**
+ * The width of the Video frame.
+ */
+@property (nonatomic, assign) int width;
+/**
+ * The height of the video frame.
+ */
+@property (nonatomic, assign) int height;
+/**
+ * The line span of Y buffer in the YUV data.
+ */
+@property (nonatomic, assign) int yStride;
+/**
+ * The line span of U buffer in the YUV data.
+ */
+@property (nonatomic, assign) int uStride;
+/**
+ * The line span of V buffer in the YUV data.
+ */
+@property (nonatomic, assign) int vStride;
+/**
+ * The pointer to the Y buffer in the YUV data.
+ */
+@property (nonatomic, assign) uint8_t* _Nullable yBuffer;
+/**
+ * The pointer to the U buffer in the YUV data.
+ */
+@property (nonatomic, assign) uint8_t* _Nullable uBuffer;
+/**
+ * The pointer to the V buffer in the YUV data.
+ */
+@property (nonatomic, assign) uint8_t* _Nullable vBuffer;
+/**
+ * The clockwise rotation information of this frame. You can set it as 0, 90, 180 or 270.
+ */
+@property (nonatomic, assign) int rotation;
+/**
+ * The timestamp to render the video stream. Use this parameter for audio-video synchronization when
+ * rendering the video.
+ *
+ * @note This parameter is for rendering the video, not capturing the video.
+ */
+@property (nonatomic, assign) int64_t renderTimeMs;
+/**
+ * The type of audio-video synchronization.
+ */
+@property (nonatomic, assign) int avSyncType;
+
+/** CVPixelBuffer
+ */
+@property(assign, nonatomic) CVPixelBufferRef _Nullable pixelBuffer;
+/**
+ * Portrait Segmentation meta buffer, dimension of which is the same as AgoraOutputVideoFrame.
+ * Pixl value is between 0-255, 0 represents totally background, 255 represents totally foreground.
+ */
+@property (nonatomic, assign) uint8_t* _Nullable alphaBuffer;
+
+@end
+
+/** Configurations of built-in encryption schemas.
+ */
+__attribute__((visibility("default"))) @interface AgoraEncryptionConfig: NSObject
+
+ /** Encryption mode. The default encryption mode is `AgoraEncryptionModeAES128GCM2`. See AgoraEncryptionMode.
+ */
+ @property (assign, nonatomic) AgoraEncryptionMode encryptionMode;
+
+ /** Encryption key in string type.
+
+ **Note**
+
+ If you do not set an encryption key or set it as `nil`, you cannot use the built-in encryption, and the SDK returns `-2` (`AgoraErrorCodeInvalidArgument`).
+ */
+ @property (copy, nonatomic) NSString * _Nullable encryptionKey;
+ @property (strong, nonatomic) NSData * _Nullable encryptionKdfSalt;
+ @property (assign, nonatomic) BOOL datastreamEncryptionEnabled;
+ @end
+
+/** AgoraUserInfo.
+ */
+__attribute__((visibility("default"))) @interface AgoraUserInfo: NSObject
+
+ /** The user ID
+ */
+@property(assign, nonatomic) NSUInteger uid;
+
+ /** The user account
+ */
+ @property (copy, nonatomic) NSString * _Nullable userAccount;
+ @end
+
+/** Client role options for the AgoraRtcEngineKit instance.
+ */
+__attribute__((visibility("default"))) @interface AgoraClientRoleOptions: NSObject
+
+/** Audicnce latency level. The default level is `AgoraAudienceLatencyLevelUltraLowLatency`. See AgoraAudienceLatencyLevelType.
+ */
+@property (assign, nonatomic) AgoraAudienceLatencyLevelType audienceLatencyLevel;
+
+@end
+
+/** The configuration of camera capturer.
+ */
+__attribute__((visibility("default"))) @interface AgoraCameraCapturerConfiguration: NSObject
+/** The camera direction. See AgoraCameraDirection:
+
+ - AgoraCameraDirectionRear: The rear camera.
+ - AgoraCameraDirectionFront: The front camera.
+ */
+#if TARGET_OS_IOS
+@property (assign, nonatomic) AgoraCameraDirection cameraDirection;
+#elif TARGET_OS_MAC
+/**
+ *The device ID of the playback device.
+ */
+@property (copy, nonatomic) NSString * _Nullable deviceId;
+#endif
+
+/**
+ * The dimensions of camera capture.
+ */
+@property(assign, nonatomic) CGSize dimensions;
+
+/** Frame rate of the camera capture.
+ */
+@property(assign, nonatomic) int frameRate;
+
+/** Follow the dimension ratio of setVideoEncoderConfiguration
+ * - YES: (Default) follow the dimension ratio.
+ * - NO: Do not follow the dimension ratio.
+ */
+@property(assign, nonatomic) BOOL followEncodeDimensionRatio;
+
+@end
+
+/** the configuration of datastream.
+ */
+__attribute__((visibility("default"))) @interface AgoraDataStreamConfig: NSObject
+
+@property (assign, nonatomic) BOOL ordered;
+
+@property (assign, nonatomic) BOOL syncWithAudio;
+@end
+
+
+/** The definition of AgoraChannelMediaRelayInfo.
+ */
+__attribute__((visibility("default"))) @interface AgoraChannelMediaRelayInfo: NSObject
+/** The token that enables the user to join the channel.
+ */
+@property (copy, nonatomic) NSString * _Nullable token;
+/** The channel name.
+ */
+@property (copy, nonatomic) NSString * _Nullable channelName;
+/** The user ID.
+ */
+@property (assign, nonatomic) NSUInteger uid;
+/** Initializes the AgoraChannelMediaRelayInfo object
+
+ @param token The token that enables the user to join the channel.
+ */
+- (instancetype _Nonnull)initWithToken:(NSString *_Nullable)token NS_SWIFT_NAME(init(token:));
+@end
+
+/** The definition of AgoraChannelMediaRelayConfiguration.
+ */
+__attribute__((visibility("default"))) @interface AgoraChannelMediaRelayConfiguration: NSObject
+/** The information of the destination channel: AgoraChannelMediaRelayInfo. It contains the following members:
+
+ - `channelName`: The name of the destination channel.
+ - `uid`: ID of the broadcaster in the destination channel. The value ranges from 0 to (232-1). To avoid UID conflicts, this `uid` must be different from any other UIDs in the destination channel. The default value is 0, which means the SDK generates a random UID.
+ - `token`: The token for joining the destination channel. It is generated with the `channelName` and `uid` you set in `destinationInfos`.
+
+ - If you have not enabled the App Certificate, set this parameter as the default value `nil`, which means the SDK applies the App ID.
+ - If you have enabled the App Certificate, you must use the `token` generated with the `channelName` and `uid`.
+ */
+@property (strong, nonatomic, readonly) NSDictionary *_Nullable destinationInfos;
+/** The information of the source channel: AgoraChannelMediaRelayInfo. It contains the following members:
+
+ - `channelName`: The name of the source channel. The default value is `nil`, which means the SDK applies the name of the current channel.
+ - `uid`: ID of the broadcaster whose media stream you want to relay. The default value is 0, which means the SDK generates a random UID. You must set it as 0.
+ - `token`: The token for joining the source channel. It is generated with the `channelName` and `uid` you set in `sourceInfo`.
+
+ - If you have not enabled the App Certificate, set this parameter as the default value `nil`, which means the SDK applies the App ID.
+ - If you have enabled the App Certificate, you must use the `token` generated with the `channelName` and `uid`, and the `uid` must be set as 0.
+ */
+@property (strong, nonatomic) AgoraChannelMediaRelayInfo *_Nonnull sourceInfo;
+/** Sets the information of the destination channel.
+
+ If you want to relay the media stream to multiple channels, call this method as many times (at most four).
+
+ @param destinationInfo The information of the destination channel: AgoraChannelMediaRelayInfo. It contains the following members:
+
+ - `channelName`: The name of the destination channel.
+ - `uid`: ID of the broadcaster in the destination channel. The value ranges from 0 to (232-1). To avoid UID conflicts, this `uid` must be different from any other UIDs in the destination channel. The default value is 0, which means the SDK generates a random UID.
+ - `token`: The token for joining the destination channel. It is generated with the `channelName` and `uid` you set in `destinationInfo`.
+
+ - If you have not enabled the App Certificate, set this parameter as the default value `nil`, which means the SDK applies the App ID.
+ - If you have enabled the App Certificate, you must use the `token` generated with the `channelName` and `uid`.
+
+ @param channelName The name of the destination channel. Ensure that the value of this parameter is the same as that of the `channelName` member in `destinationInfo`.
+
+ @return - YES: Success.
+ - NO: Failure.
+ */
+- (BOOL)setDestinationInfo:(AgoraChannelMediaRelayInfo *_Nonnull)destinationInfo forChannelName:(NSString *_Nonnull)channelName NS_SWIFT_NAME(setDestinationInfo(_:forChannelName:));
+/** Removes the destination channel.
+
+ @param channelName The name of the destination channel.
+
+ @return - YES: Success.
+ - NO: Failure.
+ */
+- (BOOL)removeDestinationInfoForChannelName:(NSString *_Nonnull)channelName NS_SWIFT_NAME(removeDestinationInfo(forChannelName:));
+@end
+
+
+/** The image enhancement options in [setBeautyEffectOptions]([AgoraRtcEngineKit setBeautyEffectOptions:options:]). */
+__attribute__((visibility("default"))) @interface AgoraBeautyOptions : NSObject
+
+/** The lightening contrast level
+
+[AgoraLighteningContrastLevel](AgoraLighteningContrastLevel), used with the lighteningLevel property:
+
+- 0: Low contrast level.
+- 1: (Default) Normal contrast level.
+- 2: High contrast level.
+*/
+@property(nonatomic, assign) AgoraLighteningContrastLevel lighteningContrastLevel;
+
+/** The brightness level.
+
+The default value is 0.7. The value ranges from 0.0 (original) to 1.0.
+ */
+@property(nonatomic, assign) float lighteningLevel;
+
+/** The smoothness level.
+
+The default value is 0.5. The value ranges from 0.0 (original) to 1.0. This parameter is usually used to remove blemishes.
+ */
+@property(nonatomic, assign) float smoothnessLevel;
+
+/** The redness level.
+
+The default value is 0.1. The value ranges from 0.0 (original) to 1.0. This parameter adjusts the red saturation level.
+*/
+@property(nonatomic, assign) float rednessLevel;
+
+/** The sharpness level.
+
+The default value is 0.1. The value ranges from 0.0 (original) to 1.0.
+*/
+@property(nonatomic, assign) float sharpnessLevel;
+
+@end
+
+/**
+ The video noise reduction options.
+
+ **Since** v3.6.2
+ */
+__attribute__((visibility("default"))) @interface AgoraVideoDenoiserOptions : NSObject
+
+/** The video noise reduction mode. See AgoraVideoDenoiserMode.
+ */
+@property(nonatomic, assign) AgoraVideoDenoiserMode mode;
+
+/** The video noise reduction level. See AgoraVideoDenoiserLevel.
+ */
+@property(nonatomic, assign) AgoraVideoDenoiserLevel level;
+
+@end
+
+/**
+ The video noise reduction options.
+
+ **Since** v3.6.2
+ */
+__attribute__((visibility("default"))) @interface AgoraLowlightEnhanceOptions : NSObject
+
+/** The low-light enhancement mode. See AgoraLowlightEnhanceMode. */
+@property(nonatomic, assign) AgoraLowlightEnhanceMode mode;
+
+/** The low-light enhancement level. See AgoraLowlightEnhanceLevel. */
+@property(nonatomic, assign) AgoraLowlightEnhanceLevel level;
+
+@end
+
+/**
+ The color enhancement options.
+
+ **Since** v3.6.2
+ */
+__attribute__((visibility("default"))) @interface AgoraColorEnhanceOptions : NSObject
+
+/** The level of color enhancement. The value range is [0.0,1.0]. `0.0` is the default value, which means no color enhancement is applied to the video. The higher the value, the higher the level of color enhancement. */
+@property(nonatomic, assign) float strengthLevel;
+
+/** The level of skin tone protection. The value range is [0.0,1.0]. `0.0` means no skin tone protection. The higher the value, the higher the level of skin tone protection. The default value is `1.0.` When the level of color enhancement is higher, the portrait skin tone can be significantly distorted, so you need to set the level of skin tone protection; when the level of skin tone protection is higher, the color enhancement effect can be slightly reduced. Therefore, to get the best color enhancement effect, Agora recommends that you adjust strengthLevel and skinProtectLevel to get the most appropriate values. */
+@property(nonatomic, assign) float skinProtectLevel;
+
+@end
+
+
+/** The custom background image.
+ */
+__attribute__((visibility("default"))) @interface AgoraVirtualBackgroundSource : NSObject
+
+/** The type of the custom background image. See AgoraVirtualBackgroundSourceType.
+ */
+@property(nonatomic, assign) AgoraVirtualBackgroundSourceType backgroundSourceType NS_SWIFT_NAME(backgroundSourceType);
+
+/** The color of the custom background image. The format is a hexadecimal
+ integer defined by RGB, without the # sign, such as `0xFFB6C1` for light pink.
+ The default value is `0xFFFFFF`, which signifies white. The value range is
+ [0x000000,0xFFFFFF]. If the value is invalid, the SDK replaces the original
+ background image with a white background image.
+ Note: This parameter takes effect only when the type of the custom
+ background image is AgoraVirtualBackgroundColor
.
+ */
+@property(nonatomic, assign) NSUInteger color NS_SWIFT_NAME(color);
+
+/** The local absolute path of the custom background image. PNG and JPG formats
+ are supported. If the path is invalid, the SDK replaces the original
+ background image with a white background image.
+ Note: This parameter takes effect only when the type of the custom
+ background image is AgoraVirtualBackgroundImg
.
+ */
+@property(nonatomic, copy) NSString* _Nullable source NS_SWIFT_NAME(source);
+
+/** Background blur degree, for example: 1 2 3 */
+@property(nonatomic, assign) AgoraBlurDegree blurDegree;
+
+@end
+
+/** The custom green capacity.
+ */
+__attribute__((visibility("default"))) @interface AgoraSegmentationProperty: NSObject
+
+@property(nonatomic, assign) SegModelType modelType;
+
+@property(nonatomic, assign) float greenCapacity;
+
+@end
+
+
+/** The definition of AgoraTranscodingVideoStream.
+ */
+__attribute__((visibility("default"))) @interface AgoraTranscodingVideoStream: NSObject
+/**
+ * Source type of video stream.
+ */
+@property (assign, nonatomic) AgoraVideoSourceType sourceType;
+/**
+ * Remote user uid if sourceType is AgoraMediaSourceTypeRemote.
+ */
+@property (assign, nonatomic) NSUInteger remoteUserUid;
+/**
+ * RTC image if sourceType is AgoraMediaSourceTypeRtcImage.
+ */
+@property (copy, nonatomic) NSString * _Nullable imageUrl;
+/**
+ * MediaPlayer id if sourceType is AgoraMediaSourceTypeMediaPlayer.
+ */
+@property(assign, nonatomic) NSUInteger mediaPlayerId;
+/**
+ * Position and size of the video frame.
+ */
+@property (assign, nonatomic) CGRect rect;
+/**
+ * The layer of the video frame that ranges from 1 to 100:
+ - 1: (Default) The lowest layer.
+ - 100: The highest layer.
+ */
+@property (assign, nonatomic) NSInteger zOrder;
+/**
+ * The transparency of the video frame.
+ */
+@property(assign, nonatomic) double alpha;
+/**
+ * Mirror of the source video frame (only valid for camera streams)
+ */
+@property(assign, nonatomic) BOOL mirror;
+
+@end
+__attribute__((visibility("default"))) @interface AgoraVideoLayout: NSObject
+@property(copy, nonatomic) NSString* _Nonnull channelId NS_SWIFT_NAME(channelId);
+@property (assign, nonatomic) NSUInteger uid NS_SWIFT_NAME(uid);
+@property(copy, nonatomic) NSString* _Nullable strUid NS_SWIFT_NAME(strUid);
+@property (assign, nonatomic) NSUInteger videoState NS_SWIFT_NAME(videoState);
+@property (assign, nonatomic) NSUInteger x NS_SWIFT_NAME(x);
+@property (assign, nonatomic) NSUInteger y NS_SWIFT_NAME(y);
+@property (assign, nonatomic) NSUInteger width NS_SWIFT_NAME(width);
+@property (assign, nonatomic) NSUInteger height NS_SWIFT_NAME(height);
+@end
+/** The definition of AgoraVideoLayoutInfo.
+ */
+__attribute__((visibility("default"))) @interface AgoraVideoLayoutInfo: NSObject
+@property (assign, nonatomic) NSUInteger width NS_SWIFT_NAME(width);
+@property (assign, nonatomic) NSUInteger height NS_SWIFT_NAME(height);
+@property (assign, nonatomic) NSUInteger layoutCount NS_SWIFT_NAME(layoutCount);
+@property(copy, nonatomic) NSArray *_Nullable layoutList NS_SWIFT_NAME(layoutList);
+@end
+
+/** The definition of AgoraLocalTranscoderConfiguration.
+ */
+__attribute__((visibility("default"))) @interface AgoraLocalTranscoderConfiguration: NSObject
+/**
+ * The video stream layout configuration in the transcoder.
+ */
+@property(copy, nonatomic) NSArray *_Nullable videoInputStreams;
+/**
+ * The video encoder configuration of transcoded video.
+ */
+@property (strong, nonatomic) AgoraVideoEncoderConfiguration *_Nonnull videoOutputConfiguration;
+
+/**
+ * Whether to use the timestamp when the primary camera captures the video frame as the timestamp of the mixed video frame.
+ * - true: (Default) Use the timestamp of the captured video frame as the timestamp of the mixed video frame.
+ * - false: Do not use the timestamp of the captured video frame as the timestamp of the mixed video frame. use the timestamp when the mixed video frame is constructed Instead.
+ */
+@property(assign, nonatomic) BOOL syncWithPrimaryCamera;
+
+@end
+
+/** The definition of the screen sharing encoding parameters.
+ */
+__attribute__((visibility("default"))) @interface AgoraScreenCaptureParameters: NSObject
+/**
+ * The dimensions of the shared region in terms of width × height. The default value is 0, which means
+ * the original dimensions of the shared screen.
+ */
+@property (assign, nonatomic) CGSize dimensions;
+/**
+ * The frame rate (fps) of the shared region. The default value is 5. We do not recommend setting
+ * this to a value greater than 15.
+ */
+@property (assign, nonatomic) NSInteger frameRate;
+/**
+ * The bitrate (Kbps) of the shared region. The default value is 0, which means the SDK works out a bitrate
+ * according to the dimensions of the current screen.
+ */
+@property (assign, nonatomic) NSInteger bitrate;
+
+/** Sets whether to capture the mouse for screen sharing.
+
+- YES: (Default) Capture the mouse.
+- NO: Do not capture the mouse.
+ */
+@property(assign, nonatomic) BOOL captureMouseCursor;
+
+/** Whether to bring the window to the front when calling [startScreenCaptureByWindowId]([AgoraRtcEngineKit startScreenCaptureByWindowId:rectangle:parameters:]) to share the window:
+
+ - YES: Bring the window to the front.
+ - NO: (Default) Do not bring the window to the front.
+
+ @note Due to system limitations, `windowFocus` only supports bringing the main window of an application to the front.
+
+ */
+@property(assign, nonatomic) BOOL windowFocus;
+
+/** A list of IDs of windows to be blocked.
+
+ When calling [startScreenCaptureByDisplayId]([AgoraRtcEngineKit startScreenCaptureByDisplayId:rectangle:parameters:])
+ and pass `0` in the `displayId` parameter to start sharing a main screen, you can use this parameter to block the specified windows. When calling
+ [updateScreenCaptureParameters]([AgoraRtcEngineKit updateScreenCaptureParameters:]) to update the configuration for the main screen sharing, you can use this
+ parameter to dynamically block the specified windows during the main screen sharing.
+
+ */
+@property(copy, nonatomic) NSArray* _Nullable excludeWindowList;
+
+/** (macOS only) Determines whether to place a border around the shared window or screen:
+
+ - YES: Place a border.
+ - NO: (Default) Do not place a border.
+
+ @note When you share a part of a window or screen, the SDK places a border around the entire window or screen if you set `highLighted` as YES.
+
+ */
+@property(assign, nonatomic) BOOL highLighted;
+/** (macOS only) The color of the border in RGBA format. The default value is 0xFF8CBF26.
+
+ on macOS, `COLOR_CLASS` refers to `NSColor`.
+
+ */
+@property(strong, nonatomic) COLOR_CLASS* _Nullable highLightColor;
+/** (macOS only) The width (px) of the border. Defaults to 0, and the value range is [0,50].
+
+ */
+@property(assign, nonatomic) NSUInteger highLightWidth;
+
+@end
+
+#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC))
+/** The configuration of camera capturer.
+ */
+__attribute__((visibility("default"))) @interface AgoraScreenCaptureConfiguration: NSObject
+/**
+ * Whether to capture the window on the screen:
+ * - `true`: Capture the window.
+ * - `false`: (Default) Capture the screen, not the window.
+ */
+@property(assign, nonatomic) BOOL isCaptureWindow;
+/**
+ * (macOS only) The display ID of the screen.
+ */
+@property(assign, nonatomic) NSInteger displayId;
+/**
+ * (For Windows and macOS only) The window ID.
+ * @note This parameter takes effect only when you want to capture the window.
+ */
+
+@property(assign, nonatomic) NSInteger windowId;
+
+/**
+ * (For Windows and macOS only) The screen capture configuration. For details, see ScreenCaptureParameters.
+ */
+@property(strong, nonatomic) AgoraScreenCaptureParameters* _Nonnull params;
+/**
+ * (For Windows and macOS only) The relative position of the shared region to the whole screen. For details, see Rectangle.
+ *
+ * If you do not set this parameter, the SDK shares the whole screen. If the region you set exceeds the boundary of the
+ * screen, only the region within in the screen is shared. If you set width or height in Rectangle as 0, the whole
+ * screen is shared.
+ */
+@property(assign, nonatomic) CGRect regionRect;
+
+@end
+#endif
+
+__attribute__((visibility("default"))) @interface AgoraScreenVideoParameters : NSObject
+
+/** CGSizezero Since the applicable below 720p
+
+ You can customize the dimension, or select from the following list:
+
+ - AgoraVideoDimension120x120
+ - AgoraVideoDimension160x120
+ - AgoraVideoDimension180x180
+ - AgoraVideoDimension240x180
+ - AgoraVideoDimension320x180
+ - AgoraVideoDimension240x240
+ - AgoraVideoDimension320x240
+ - AgoraVideoDimension424x240
+ - AgoraVideoDimension360x360
+ - AgoraVideoDimension480x360
+ - AgoraVideoDimension640x360
+ - AgoraVideoDimension480x480
+ - AgoraVideoDimension640x480
+ - AgoraVideoDimension840x480
+ - AgoraVideoDimension960x540
+ - AgoraVideoDimension960x720
+ - AgoraVideoDimension1280x720
+ - AgoraVideoDimension1920x1080 (macOS only)
+
+ Note:
+
+ - The dimension does not specify the orientation mode of the output ratio. For how to set the video orientation, see [AgoraVideoOutputOrientationMode](AgoraVideoOutputOrientationMode).
+ - Whether 720p can be supported depends on the device. If the device cannot support 720p, the frame rate will be lower than the one listed in the table. Agora optimizes the video in lower-end devices.
+ - iPhones do not support video frame dimensions above 720p.
+
+ */
+@property(assign, nonatomic) CGSize dimensions;
+/** The frame rate of the video (fps).
+
+ You can either set the frame rate manually or choose from the following options. The default value is 15. We do not recommend setting this to a value greater than 30.
+
+ * AgoraVideoFrameRateFps1(1): 1 fps
+ * AgoraVideoFrameRateFps7(7): 7 fps
+ * AgoraVideoFrameRateFps10(10): 10 fps
+ * AgoraVideoFrameRateFps15(15): 15 fps
+ * AgoraVideoFrameRateFps24(24): 24 fps
+ * AgoraVideoFrameRateFps30(30): 30 fps
+ * AgoraVideoFrameRateFps60(30): 60 fps (macOS only)
+ */
+@property(assign, nonatomic) AgoraVideoFrameRate frameRate;
+/** The bitrate of the video.
+
+ Sets the video bitrate (Kbps). Refer to the table below and set your bitrate. If you set a bitrate beyond the proper range, the SDK automatically adjusts it to a value within the range. You can also choose from the following options:
+
+ - AgoraVideoBitrateStandard: (recommended) the standard bitrate mode. In this mode, the bitrates differ between the interactive live streaming and Communication profiles:
+
+ - Communication profile: the video bitrate is the same as the base bitrate.
+ - Interactive live streaming profile: the video bitrate is twice the base bitrate.
+
+ - AgoraVideoBitrateCompatible: the compatible bitrate mode. In this mode, the bitrate stays the same regardless of the profile. In the interactive live streaming profile, if you choose this mode, the video frame rate may be lower than the set value.
+
+Agora uses different video codecs for different profiles to optimize the user experience. For example, the Communication profile prioritizes the smoothness while the interactive live streaming profile prioritizes the video quality (a higher bitrate). Therefore, Agora recommends setting this parameter as AgoraVideoBitrateStandard.
+
+**Video Bitrate Table**
+
+| Resolution | Frame Rate (fps) | Base Bitrate (Kbps, for Communication) | Live Bitrate (Kbps, for Live Broadcast) |
+|-------------------|------------------|----------------------------------------|-----------------------------------------|
+| 160 * 120 | 15 | 65 | 130 |
+| 120 * 120 | 15 | 50 | 100 |
+| 320 * 180 | 15 | 140 | 280 |
+| 180 * 180 | 15 | 100 | 200 |
+| 240 * 180 | 15 | 120 | 240 |
+| 320 * 240 | 15 | 200 | 400 |
+| 240 * 240 | 15 | 140 | 280 |
+| 424 * 240 | 15 | 220 | 440 |
+| 640 * 360 | 15 | 400 | 800 |
+| 360 * 360 | 15 | 260 | 520 |
+| 640 * 360 | 30 | 600 | 1200 |
+| 360 * 360 | 30 | 400 | 800 |
+| 480 * 360 | 15 | 320 | 640 |
+| 480 * 360 | 30 | 490 | 980 |
+| 640 * 480 | 15 | 500 | 1000 |
+| 480 * 480 | 15 | 400 | 800 |
+| 640 * 480 | 30 | 750 | 1500 |
+| 480 * 480 | 30 | 600 | 1200 |
+| 848 * 480 | 15 | 610 | 1220 |
+| 848 * 480 | 30 | 930 | 1860 |
+| 640 * 480 | 10 | 400 | 800 |
+| 1280 * 720 | 15 | 1130 | 2260 |
+| 1280 * 720 | 30 | 1710 | 3420 |
+| 960 * 720 | 15 | 910 | 1820 |
+| 960 * 720 | 30 | 1380 | 2760 |
+| 1920 * 1080 | 15 | 2080 | 4160 |
+| 1920 * 1080 | 30 | 3150 | 6300 |
+| 1920 * 1080 | 60 | 4780 | 6500 |
+
+
+**Note:**
+
+The base bitrate in this table applies to the Communication profile. The interactive live streaming profile generally requires a higher bitrate for better video quality. Agora recommends setting the bitrate mode as AgoraVideoBitrateStandard. You can also set the bitrate as twice the base bitrate.
+
+
+*/
+@property(assign, nonatomic) NSInteger bitrate;
+
+/** contentHint The content hint for screen sharing, see [AgoraVideoContentHint](AgoraVideoContentHint).
+ */
+@property(assign, nonatomic) AgoraVideoContentHint contentHint;
+
+@end
+
+__attribute__((visibility("default"))) @interface AgoraScreenAudioParameters : NSObject
+
+@property(assign, nonatomic) NSInteger captureSignalVolume;
+
+@end
+
+__attribute__((visibility("default"))) @interface AgoraScreenCaptureParameters2 : NSObject
+/**
+ * when captureAudio is YES, ReplayKit will push sample buffer with RPSampleBufferTypeAudioApp, default NO.
+ */
+@property(assign, nonatomic) BOOL captureAudio;
+/**
+ * screen share with audio parameters
+ */
+@property(strong, nonatomic) AgoraScreenAudioParameters* _Nonnull audioParams;
+/**
+ * when captureVideo is YES, ReplayKit will push sample buffer with RPSampleBufferTypeVideo, default YES.
+ */
+@property(assign, nonatomic) BOOL captureVideo;
+/**
+ * screen share with video parameters
+ */
+@property(strong, nonatomic) AgoraScreenVideoParameters* _Nonnull videoParams;
+@end
+
+/** Configurations of SimulcastStreamConfig.
+ */
+
+__attribute__((visibility("default"))) @interface AgoraAudioRecordingConfiguration: NSObject
+/**
+ * The absolute path (including the filename extensions) of the recording file. For example: `/var/mobile/Containers/Data/audio.aac`.
+ * @note Ensure that the path you specify exists and is writable.
+ */
+@property (copy, nonatomic) NSString * _Nullable filePath;
+/**
+ * Recording sample rate (Hz). The following values are supported:
+ * - 16000
+ * - (Default) 32000
+ * - 44100
+ * - 48000
+ * @note If this parameter is set to `44100` or `48000`, for better recording effects, Agora recommends recording WAV
+ * files or AAC files whose `quality` is `AgoraAudioRecordingQualityMedium` or `AgoraAudioRecordingQualityHigh`.
+ */
+@property (assign, nonatomic) NSUInteger sampleRate;
+/**
+ * Recording content. See AgoraAudioFileRecordingType.
+ */
+@property (assign, nonatomic) AgoraAudioFileRecordingType fileRecordOption;
+/**
+ * Audio recording quality. See AgoraAudioRecordingQuality.
+ * @note This parameter applies for AAC files only.
+ */
+@property (assign, nonatomic) AgoraAudioRecordingQuality quality;
+
+/**
+ * Recording channel.The following values are supported:
+ * - (Default) 1
+ * - 2
+ */
+@property (assign, nonatomic) NSInteger recordingChannel;
+
+@end
+
+/** Configurations of SimulcastStreamConfig.
+ */
+__attribute__((visibility("default"))) @interface AgoraSimulcastStreamConfig: NSObject
+
+/**
+ * The video bitrate (Kbps).
+ */
+ @property (assign, nonatomic) int kBitrate;
+/**
+ * The video framerate.
+ */
+ @property (assign, nonatomic) int framerate;
+ /**
+ * The video frame dimension.
+ */
+ @property (assign, nonatomic) CGSize dimensions;
+ @end
+
+/** The AgoraMediaStreamInfo class, reporting the whole detailed information of
+ the media stream.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcMediaStreamInfo : NSObject
+/** The index of the media stream. */
+@property(nonatomic, assign) NSInteger streamIndex;
+/** The type of the media stream. See AgoraMediaStreamType for details. */
+@property(nonatomic, assign) AgoraMediaStreamType streamType;
+/** The codec of the media stream. */
+@property(nonatomic, copy) NSString *_Nonnull codecName;
+/** The language of the media stream. */
+@property(nonatomic, copy) NSString *_Nullable language;
+/** For video stream, gets the frame rate (fps). */
+@property(nonatomic, assign) NSInteger videoFrameRate;
+/** For video stream, gets the bitrate (bps). */
+@property(nonatomic, assign) NSInteger videoBitRate;
+/** For video stream, gets the width (pixel) of the video. */
+@property(nonatomic, assign) NSInteger videoWidth;
+/** For video stream, gets the height (pixel) of the video. */
+@property(nonatomic, assign) NSInteger videoHeight;
+/** For the audio stream, gets the sample rate (Hz). */
+@property(nonatomic, assign) NSInteger audioSampleRate;
+/** For the audio stream, gets the channel number. */
+@property(nonatomic, assign) NSInteger audioChannels;
+/** The total duration (s) of the media stream. */
+@property(nonatomic, assign) NSInteger duration;
+/** The rotation of the video stream. */
+@property(nonatomic, assign) NSInteger rotation;
+
+@end
+
+__attribute__((visibility("default"))) @interface AgoraAudioSpectrumInfo : NSObject
+
+/** User ID of the speaker. */
+@property(nonatomic, assign) NSInteger uid;
+@property(nonatomic, strong) NSArray * _Nullable audioSpectrumData;
+
+@end
+
+/**
+ * The configurations for the audio encoded freame.
+ */
+__attribute__((visibility("default"))) @interface AgoraAudioEncodedFrameDelegateConfig: NSObject
+/**
+ * The position where SDK record the audio, and callback to encoded audio frame observer.
+ */
+@property (assign, nonatomic) AgoraAudioEncodedFrameDelegatePosition postionType;
+/**
+ * audio encoding type.
+ */
+@property (assign, nonatomic) AgoraAudioEncodingType encodingType;
+@end
+
+__attribute__((visibility("default"))) @interface AgoraContentInspectModule: NSObject
+@property (assign, nonatomic) AgoraContentInspectType type;
+
+@property (assign, nonatomic) NSInteger interval;
+@end
+
+__attribute__((visibility("default"))) @interface AgoraContentInspectConfig: NSObject
+@property (nonatomic, copy) NSString* _Nullable extraInfo;
+@property(copy, nonatomic) NSArray* _Nullable modules;
+@end
+/**
+ * The AgoraRtcConnection for the AgoraRtcEngineKitEx.
+ */
+__attribute__((visibility("default"))) @interface AgoraRtcConnection: NSObject
+
+/**
+ * Init AgoraRtcConnection with channelId and localUid
+ *
+ * @param channelId Unique channel name for the AgoraRTC session in the string.
+ * @param localUid Local User ID. A 32-bit unsigned integer.
+ * @return AgoraRtcConnection.
+ */
+- (instancetype _Nonnull)initWithChannelId:(NSString *_Nonnull)channelId localUid:(NSInteger)localUid;
+
+/* channelId Unique channel name for the AgoraRTC session in the string
+ * format. The string length must be less than 64 bytes. Supported character
+ * scopes are:
+ * - All lowercase English letters: a to z.
+ * - All uppercase English letters: A to Z.
+ * - All numeric characters: 0 to 9.
+ * - The space character.
+ * - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
+ */
+@property (nonatomic, copy) NSString *_Nonnull channelId;
+/* uid Local User ID. A 32-bit unsigned integer with a value ranging from 1 to
+ * (232-1). The `uid` must be unique and not set to 0 . Your app
+ * must record and maintain the returned `uid` since the SDK does not do so.
+ */
+@property (nonatomic, assign) NSUInteger localUid;
+
+@end
+/**
+ * remote video subscription options
+ */
+__attribute__((visibility("default"))) @interface AgoraVideoSubscriptionOptions: NSObject
+
+/*
+* The type of the video stream to subscribe to.
+*
+* The default value is `VIDEO_STREAM_HIGH`, which means the high-quality
+* video stream.
+*/
+@property (nonatomic, assign) AgoraVideoStreamType type;
+/*
+* Whether to subscribe to encoded video data only:
+* - `true`: Subscribe to encoded video data only.
+* - `false`: (Default) Subscribe to decoded video data.
+*/
+@property (nonatomic, assign) bool encodedFrameOnly;
+
+@end
+/**
+ * The configurations for the audio encoded freame.
+ */
+__attribute__((visibility("default"))) @interface AgoraEncodedVideoFrameInfo: NSObject
+
+/**
+ * The video codec: #VIDEO_CODEC_TYPE.
+ */
+@property (assign, nonatomic) AgoraVideoCodecType codecType;
+/**
+ * The width (px) of the video.
+ */
+@property (assign, nonatomic) NSInteger width;
+/**
+ * The height (px) of the video.
+ */
+@property (assign, nonatomic) NSInteger height;
+/**
+ * The number of video frames per second.
+ * This value will be used for calculating timestamps of the encoded image.
+ * If framesPerSecond equals zero, then real timestamp will be used.
+ * Otherwise, timestamp will be adjusted to the value of framesPerSecond set.
+ */
+@property (assign, nonatomic) NSInteger framesPerSecond;
+/**
+ * The frame type of the encoded video frame: #VIDEO_FRAME_TYPE.
+ */
+@property (assign, nonatomic) AgoraVideoFrameType frameType;
+/**
+ * The rotation information of the encoded video frame: #VIDEO_ORIENTATION.
+ */
+@property (assign, nonatomic) NSInteger rotation;
+/**
+ * The track ID of the video frame.
+ */
+@property (assign, nonatomic) NSInteger trackId; // This can be reserved for multiple video tracks, we need to create different ssrc
+ // and additional payload for later implementation.
+/**
+ * This is a input parameter which means the timestamp for capturing the video.
+ */
+@property (assign, nonatomic) NSInteger captureTimeMs;
+/**
+ * This is a output parameter which means the timestamp for decoding the video.
+ */
+@property (assign, nonatomic) NSInteger decodeTimeMs;
+/**
+ * ID of the user.
+ */
+@property (assign, nonatomic) NSInteger uid;
+/**
+ * The stream type of video frame.
+ */
+@property (assign, nonatomic) AgoraVideoStreamType streamType;
+@end
+
+NS_SWIFT_NAME(LogUploadServerInfo) __attribute__((visibility("default"))) @interface LogUploadServerInfo : NSObject
+/** Log upload server domain
+ */
+@property(copy, nonatomic) NSString* _Nullable serverDomain;
+/** Log upload server path
+ */
+@property(copy, nonatomic) NSString* _Nullable serverPath;
+/** Log upload server port
+ */
+@property(assign, nonatomic) NSInteger serverPort;
+/** Whether to use HTTPS request:
+ - true: Use HTTPS request
+ - fasle: Use HTTP request
+ */
+@property(assign, nonatomic) BOOL serverHttps;
+@end
+
+NS_SWIFT_NAME(AdvancedConfigInfo) __attribute__((visibility("default"))) @interface AdvancedConfigInfo : NSObject
+/** Log upload server
+ */
+@property(strong, nonatomic) LogUploadServerInfo* _Nullable logUploadServer;
+@end
+
+NS_SWIFT_NAME(AgoraLocalAccessPointConfiguration) __attribute__((visibility("default"))) @interface AgoraLocalAccessPointConfiguration : NSObject
+/** Local access point IP address list.
+ */
+@property(copy, nonatomic) NSArray* _Nullable ipList NS_SWIFT_NAME(ipList);
+/** Local access point domain list.
+ */
+@property(copy, nonatomic) NSArray* _Nullable domainList NS_SWIFT_NAME(domainList);
+/** Certificate domain name installed on specific local access point. pass "" means using sni domain on specific local access point
+ * SNI(Server Name Indication) is an extension to the TLS protocol.
+ */
+@property(copy, nonatomic) NSString* _Nullable verifyDomainName NS_SWIFT_NAME(verifyDomainName);
+/** Local proxy connection mode, connectivity first or local only.
+ */
+@property(assign, nonatomic) AgoraLocalProxyMode mode NS_SWIFT_NAME(mode);
+/** Local proxy connection, advanced config info.
+ */
+@property(strong, nonatomic) AdvancedConfigInfo* _Nullable advancedConfig NS_SWIFT_NAME(advancedConfig);
+@end
+
+/**
+ * The configuration of rhythm player,
+ * which is set in startRhythmPlayer or configRhythmPlayer.
+ */
+__attribute__((visibility("default"))) @interface AgoraRhythmPlayerConfig: NSObject
+/**
+ * The number of beats per measure. The range is 1 to 9.
+ * The default value is 4,
+ * which means that each measure contains one downbeat and three upbeats.
+ */
+@property (assign, nonatomic) int beatsPerMeasure;
+/*
+ * The range is 60 to 360.
+ * The default value is 60,
+ * which means that the rhythm player plays 60 beats in one minute.
+ */
+@property (assign, nonatomic) int beatsPerMinute;
+
+@end
+
+/** AgoraFacePositionInfo.
+ */
+NS_SWIFT_NAME(AgoraFacePositionInfo) __attribute__((visibility("default"))) @interface AgoraFacePositionInfo : NSObject
+
+/** The x coordinate (px) of the human face in the local video. Taking the top left corner of the captured video as the origin, the x coordinate represents the relative lateral displacement of the top left corner of the human face to the origin.
+ */
+@property(assign, nonatomic) NSInteger x NS_SWIFT_NAME(x);
+
+/** The y coordinate (px) of the human face in the local video. Taking the top left corner of the captured video as the origin, the y coordinate represents the relative longitudinal displacement of the top left corner of the human face to the origin.
+ */
+@property(assign, nonatomic) NSInteger y NS_SWIFT_NAME(y);
+
+/** The width (px) of the human face in the captured video.
+ */
+@property(assign, nonatomic) NSInteger width NS_SWIFT_NAME(width);
+
+/** The height (px) of the human face in the captured video.
+ */
+@property(assign, nonatomic) NSInteger height NS_SWIFT_NAME(height);
+
+/** The distance (cm) between the human face and the screen.
+ */
+@property(assign, nonatomic) NSInteger distance NS_SWIFT_NAME(distance);
+@end
+
+/** AgoraAdvancedAudioOptions.
+ */
+__attribute__((visibility("default"))) @interface AgoraAdvancedAudioOptions: NSObject
+
+@property(assign, nonatomic) AgoraAudioProcessChannels audioProcessingChannels;
+
+@end
+
+__attribute__((visibility("default"))) @interface AgoraImageTrackOptions : NSObject
+@property(copy, nonatomic) NSString *_Nullable imageUrl;
+@property(assign, nonatomic) int fps;
+@property(assign, nonatomic) AgoraVideoMirrorMode mirrorMode;
+@end
+
+/**
+ * spatial audio parameters
+ * .
+ */
+__attribute__((visibility("default"))) @interface AgoraSpatialAudioParams : NSObject
+/**
+ * Speaker azimuth in a spherical coordinate system centered on the listener.
+ */
+@property(assign, nonatomic) double speaker_azimuth;
+/**
+ * Speaker elevation in a spherical coordinate system centered on the listener.
+ */
+@property(assign, nonatomic) double speaker_elevation;
+/**
+ * Distance between speaker and listener.
+ */
+@property(assign, nonatomic) double speaker_distance;
+/**
+ * Speaker orientation [0-180], 0 degree is the same with listener orientation.
+ */
+@property(assign, nonatomic) NSInteger speaker_orientation;
+/**
+ * Enable blur or not for the speaker.
+ */
+@property(assign, nonatomic) BOOL enable_blur;
+/**
+ * Enable air absorb or not for the speaker.
+ */
+@property(assign, nonatomic) BOOL enable_air_absorb;
+/**
+ * Speaker attenuation factor.
+ */
+@property(assign, nonatomic) double speaker_attenuation;
+/**
+ * Enable doppler factor.
+ */
+@property(assign, nonatomic) BOOL enable_doppler;
+@end
+
+NS_SWIFT_NAME(AgoraEchoTestConfiguration)
+__attribute__((visibility("default"))) @interface AgoraEchoTestConfiguration : NSObject
+/** The video display view.
+
+ VIEW_CLASS is a general name for this property. See the following definitions for iOS and macOS:
+
+ - iOS: UIView
+ - MacOS: NSView
+ */
+@property(strong, nonatomic) VIEW_CLASS* _Nullable view NS_SWIFT_NAME(view);
+/** Whether to enable audio.
+ */
+@property(assign, nonatomic) BOOL enableAudio NS_SWIFT_NAME(enableAudio);
+/** Whether to enable video.
+ */
+@property(assign, nonatomic) BOOL enableVideo NS_SWIFT_NAME(enableVideo);
+/** The token for join channel.
+ */
+@property(copy, nonatomic) NSString* _Nullable token NS_SWIFT_NAME(token);
+/** The channelId.
+ */
+@property(copy, nonatomic) NSString* _Nonnull channelId NS_SWIFT_NAME(channelId);
+@end
+
+/**
+ * Indicator optimization degree.
+ */
+NS_SWIFT_NAME(AgoraWlAccStats) __attribute__((visibility("default"))) @interface AgoraWlAccStats : NSObject
+/**
+ * End-to-end delay optimization percentage.
+ */
+@property(assign, nonatomic) NSInteger e2eDelayPercent NS_SWIFT_NAME(e2eDelayPercent);
+/**
+ * Frozen Ratio optimization percentage.
+ */
+@property(assign, nonatomic) NSInteger frozenRatioPercent NS_SWIFT_NAME(frozenRatioPercent);
+/**
+ * Loss Rate optimization percentage.
+ */
+@property(assign, nonatomic) NSInteger lossRatePercent NS_SWIFT_NAME(lossRatePercent);
+@end
+
+__attribute__((visibility("default"))) @interface AgoraMediaRecorderInfo : NSObject
+
+/** Recorder file name. It contains file's absolute path.
+ */
+@property(copy, nonatomic) NSString* _Nonnull recorderFileName;
+/** Record duration (ms).
+ */
+@property(assign, nonatomic) NSUInteger durationMs;
+/** Record file size (Byte).
+ */
+@property(assign, nonatomic) NSUInteger fileSize;
+
+@end
+
+__attribute__((visibility("default"))) @interface AgoraMediaRecorderConfiguration : NSObject
+
+/** Recorder file storage path. It contains file name (absolute path), such as -xxx.flv, -xxx.mp4, etc.
+ */
+@property(copy, nonatomic) NSString* _Nonnull storagePath;
+/** Container format. See AgoraMediaRecorderContainerFormat.
+ */
+@property(assign, nonatomic) AgoraMediaRecorderContainerFormat containerFormat;
+/** Stream Type. See AgoraMediaRecorderStreamType.
+ */
+@property(assign, nonatomic) AgoraMediaRecorderStreamType streamType;
+/** Max duration (ms). Default 120000ms.
+ */
+@property(assign, nonatomic) NSUInteger maxDurationMs;
+/** Recorder information update interval (ms, [1000~10000]). If it is set to other values, there won't be any callback.
+ */
+@property(assign, nonatomic) NSUInteger recorderInfoUpdateInterval;
+
+@end
+
+#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC))
+
+/**
+ The AgoraScreenCaptureSourceInfo interface. (macOS only)
+ */
+__attribute__((visibility("default"))) @interface AgoraScreenCaptureSourceInfo : NSObject
+/** The type of the shared target. See ScreenCaptureSourceType. */
+@property(assign, nonatomic) AgoraScreenCaptureSourceType type;
+/** The window ID for a window or the display ID for a screen. */
+@property(assign, nonatomic) CGWindowID sourceId;
+/** The name of the window or screen. UTF-8 encoding. */
+@property(copy, nonatomic) NSString* _Nonnull sourceName;
+/** The image content of the thumbnail.. */
+@property(strong, nonatomic) NSImage* _Nonnull thumbImage;
+/** The image content of the icon. . */
+@property(strong, nonatomic) NSImage* _Nullable iconImage;
+/** The process to which the window belongs. UTF-8 encoding. */
+@property(copy, nonatomic) NSString* _Nonnull processPath;
+/** The name of the processName. UTF-8 encoding. */
+@property(copy, nonatomic) NSString* _Nonnull sourceTitle;
+/** The relative position of the shared region to the screen space (A virtual space include all the screens). */
+@property(assign, nonatomic) CGRect position;
+/** Determines whether the screen is the primary display:
+
+ - YES: The screen is the primary display.
+ - NO: The screen is not the primary display.
+ */
+@property(assign, nonatomic) BOOL primaryMonitor;
+
+@end
+
+#endif
+
+NS_SWIFT_NAME(AgoraExtensionInfo) __attribute__((visibility("default"))) @interface AgoraExtensionInfo : NSObject
+
+/**
+ * The type of media device.
+ */
+@property (assign, nonatomic) AgoraMediaSourceType sourceType NS_SWIFT_NAME(sourceType);
+
+/**
+ * The id of the remote user on which the extension works.
+ *
+ * @note remoteUid = 0 means that the extension works on all remote streams.
+ */
+@property (assign, nonatomic) NSUInteger remoteUid NS_SWIFT_NAME(remoteUid);
+
+/**
+ * The unique channel name for the AgoraRTC session in the string format. The string
+ * length must be less than 64 bytes. Supported character scopes are:
+ * - All lowercase English letters: a to z.
+ * - All uppercase English letters: A to Z.
+ * - All numeric characters: 0 to 9.
+ * - The space character.
+ * - Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+",
+ * "-",
+ * ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
+ */
+@property (copy, nonatomic) NSString *_Nonnull channelId NS_SWIFT_NAME(channelId);
+
+/**
+ * User ID: A 32-bit unsigned integer ranging from 1 to (2^32-1). It must be unique.
+ */
+@property (assign, nonatomic) NSUInteger localUid NS_SWIFT_NAME(localUid);
+
+@end
+
+/**
+ * The video rendering tracing result
+ */
+NS_SWIFT_NAME(AgoraVideoRenderingTracingInfo) __attribute__((visibility("default"))) @interface AgoraVideoRenderingTracingInfo : NSObject
+/**
+ * Elapsed time from the start tracing time to the time when the tracing event occurred.
+ */
+@property (assign, nonatomic) NSInteger elapsedTime NS_SWIFT_NAME(elapsedTime);
+/**
+ * Elapsed time from the start tracing time to the time when join channel.
+ *
+ * **Note**
+ * If the start tracing time is behind the time when join channel, this value will be negative.
+ */
+@property (assign, nonatomic) NSInteger start2JoinChannel NS_SWIFT_NAME(start2JoinChannel);
+/**
+ * Elapsed time from joining channel to finishing joining channel.
+ */
+@property (assign, nonatomic) NSInteger join2JoinSuccess NS_SWIFT_NAME(join2JoinSuccess);
+/**
+ * Elapsed time from finishing joining channel to remote user joined.
+ *
+ * **Note**
+ * If the start tracing time is after the time finishing join channel, this value will be
+ * the elapsed time from the start tracing time to remote user joined. The minimum value is 0.
+ */
+@property (assign, nonatomic) NSInteger joinSuccess2RemoteJoined NS_SWIFT_NAME(joinSuccess2RemoteJoined);
+/**
+ * Elapsed time from remote user joined to set the view.
+ *
+ * **Note**
+ * If the start tracing time is after the time when remote user joined, this value will be
+ * the elapsed time from the start tracing time to set the view. The minimum value is 0.
+ */
+@property (assign, nonatomic) NSInteger remoteJoined2SetView NS_SWIFT_NAME(remoteJoined2SetView);
+/**
+ * Elapsed time from remote user joined to the time subscribing remote video stream.
+ *
+ * **Note**
+ * If the start tracing time is after the time when remote user joined, this value will be
+ * the elapsed time from the start tracing time to the time subscribing remote video stream.
+ * The minimum value is 0.
+ */
+@property (assign, nonatomic) NSInteger remoteJoined2UnmuteVideo NS_SWIFT_NAME(remoteJoined2UnmuteVideo);
+/**
+ * Elapsed time from remote user joined to the remote video packet received.
+ *
+ * **Note**
+ * If the start tracing time is after the time when remote user joined, this value will be
+ * the elapsed time from the start tracing time to the time subscribing remote video stream.
+ * The minimum value is 0.
+ */
+@property (assign, nonatomic) NSInteger remoteJoined2PacketReceived NS_SWIFT_NAME(remoteJoined2PacketReceived);
+
+@end
+
+/** The configuration of custom audio track
+*/
+NS_SWIFT_NAME(AgoraAudioTrackConfig) __attribute__((visibility("default"))) @interface AgoraAudioTrackConfig : NSObject
+/**
+ * Enable local playback, enabled by default
+ * true: (Default) Enable local playback
+ * false: Do not enable local playback
+ */
+@property (assign, nonatomic) BOOL enableLocalPlayback NS_SWIFT_NAME(enableLocalPlayback);
+
+@end
diff --git a/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraOptional.h b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraOptional.h
new file mode 100644
index 0000000..97595be
--- /dev/null
+++ b/Sources/AgoraRtcKit.xcframework/ios-arm64_armv7/AgoraRtcKit.framework/Headers/AgoraOptional.h
@@ -0,0 +1,891 @@
+// Copyright (c) 2019 Agora.io. All rights reserved
+
+// This program is confidential and proprietary to Agora.io.
+// And may not be copied, reproduced, modified, disclosed to others, published
+// or used, in whole or in part, without the express prior written permission
+// of Agora.io.
+#pragma once
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+#include
+#endif
+#include
+
+#ifndef CONSTEXPR
+#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
+#define CONSTEXPR constexpr
+#else
+#define CONSTEXPR
+#endif
+#endif // !CONSTEXPR
+
+#ifndef NOEXCEPT
+#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
+#define NOEXCEPT(Expr) noexcept(Expr)
+#else
+#define NOEXCEPT(Expr)
+#endif
+#endif // !NOEXCEPT
+
+namespace agora {
+
+// Specification:
+// http://en.cppreference.com/w/cpp/utility/optional/in_place_t
+struct in_place_t {};
+
+// Specification:
+// http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
+struct nullopt_t {
+ CONSTEXPR explicit nullopt_t(int) {}
+};
+
+// Specification:
+// http://en.cppreference.com/w/cpp/utility/optional/in_place
+/*CONSTEXPR*/ const in_place_t in_place = {};
+
+// Specification:
+// http://en.cppreference.com/w/cpp/utility/optional/nullopt
+/*CONSTEXPR*/ const nullopt_t nullopt(0);
+
+// Forward declaration, which is refered by following helpers.
+template
+class Optional;
+
+namespace internal {
+
+template
+struct OptionalStorageBase {
+ // Initializing |empty_| here instead of using default member initializing
+ // to avoid errors in g++ 4.8.
+ CONSTEXPR OptionalStorageBase() : is_populated_(false), empty_('\0') {}
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ template
+ CONSTEXPR explicit OptionalStorageBase(in_place_t, Args&&... args)
+ : is_populated_(true), value_(std::forward(args)...) {}
+#else
+ CONSTEXPR explicit OptionalStorageBase(in_place_t, const T& _value)
+ : is_populated_(true), value_(_value) {}
+#endif
+ // When T is not trivially destructible we must call its
+ // destructor before deallocating its memory.
+ // Note that this hides the (implicitly declared) move constructor, which
+ // would be used for constexpr move constructor in OptionalStorage.
+ // It is needed iff T is trivially move constructible. However, the current
+ // is_trivially_{copy,move}_constructible implementation requires
+ // is_trivially_destructible (which looks a bug, cf:
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and
+ // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not
+ // necessary for this case at the moment. Please see also the destructor
+ // comment in "is_trivially_destructible = true" specialization below.
+ ~OptionalStorageBase() {
+ if (is_populated_)
+ value_.~T();
+ }
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ template
+ void Init(Args&&... args) {
+ ::new (&value_) T(std::forward(args)...);
+ is_populated_ = true;
+ }
+#else
+ void Init(const T& _value) {
+ ::new (&value_) T(_value);
+ is_populated_ = true;
+ }
+#endif
+
+ bool is_populated_;
+
+ union {
+ // |empty_| exists so that the union will always be initialized, even when
+ // it doesn't contain a value. Union members must be initialized for the
+ // constructor to be 'constexpr'.
+ char empty_;
+ T value_;
+ };
+};
+
+// Implement conditional constexpr copy and move constructors. These are
+// constexpr if is_trivially_{copy,move}_constructible::value is true
+// respectively. If each is true, the corresponding constructor is defined as
+// "= default;", which generates a constexpr constructor (In this case,
+// the condition of constexpr-ness is satisfied because the base class also has
+// compiler generated constexpr {copy,move} constructors). Note that
+// placement-new is prohibited in constexpr.
+template
+struct OptionalStorage : OptionalStorageBase {
+ // This is no trivially {copy,move} constructible case. Other cases are
+ // defined below as specializations.
+
+ // Accessing the members of template base class requires explicit
+ // declaration.
+ using OptionalStorageBase::is_populated_;
+ using OptionalStorageBase::value_;
+ using OptionalStorageBase::Init;
+
+ // Inherit constructors (specifically, the in_place constructor).
+ //using OptionalStorageBase::OptionalStorageBase;
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ template
+ CONSTEXPR explicit OptionalStorage(in_place_t in_place, Args&&... args)
+ : OptionalStorageBase(in_place, std::forward(args)...) {}
+#else
+ CONSTEXPR explicit OptionalStorage(in_place_t in_place, const T& _value)
+ : OptionalStorageBase(in_place, _value) {}
+#endif
+
+ // User defined constructor deletes the default constructor.
+ // Define it explicitly.
+ OptionalStorage() {}
+
+ OptionalStorage(const OptionalStorage& other) {
+ if (other.is_populated_)
+ Init(other.value_);
+ }
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ OptionalStorage(OptionalStorage&& other) NOEXCEPT(std::is_nothrow_move_constructible::value) {
+ if (other.is_populated_)
+ Init(std::move(other.value_));
+ }
+#endif
+};
+
+// Base class to support conditionally usable copy-/move- constructors
+// and assign operators.
+template
+class OptionalBase {
+ // This class provides implementation rather than public API, so everything
+ // should be hidden. Often we use composition, but we cannot in this case
+ // because of C++ language restriction.
+ protected:
+ CONSTEXPR OptionalBase() {}
+ CONSTEXPR OptionalBase(const OptionalBase& other) : storage_(other.storage_) {}
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ CONSTEXPR OptionalBase(OptionalBase&& other) : storage_(std::move(other.storage_)) {}
+
+ template
+ CONSTEXPR explicit OptionalBase(in_place_t, Args&&... args)
+ : storage_(in_place, std::forward(args)...) {}
+#else
+ CONSTEXPR explicit OptionalBase(in_place_t, const T& _value)
+ : storage_(in_place, _value) {}
+#endif
+
+ // Implementation of converting constructors.
+ template
+ explicit OptionalBase(const OptionalBase& other) {
+ if (other.storage_.is_populated_)
+ storage_.Init(other.storage_.value_);
+ }
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ template
+ explicit OptionalBase(OptionalBase&& other) {
+ if (other.storage_.is_populated_)
+ storage_.Init(std::move(other.storage_.value_));
+ }
+#endif
+
+ ~OptionalBase() {}
+
+ OptionalBase& operator=(const OptionalBase& other) {
+ CopyAssign(other);
+ return *this;
+ }
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ OptionalBase& operator=(OptionalBase&& other) NOEXCEPT(
+ std::is_nothrow_move_assignable::value &&
+ std::is_nothrow_move_constructible::value) {
+ MoveAssign(std::move(other));
+ return *this;
+ }
+#endif
+
+ template
+ void CopyAssign(const OptionalBase& other) {
+ if (other.storage_.is_populated_)
+ InitOrAssign(other.storage_.value_);
+ else
+ FreeIfNeeded();
+ }
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ template
+ void MoveAssign(OptionalBase&& other) {
+ if (other.storage_.is_populated_)
+ InitOrAssign(std::move(other.storage_.value_));
+ else
+ FreeIfNeeded();
+ }
+#endif
+
+ template
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ void InitOrAssign(U&& value) {
+ if (storage_.is_populated_)
+ storage_.value_ = std::forward(value);
+ else
+ storage_.Init(std::forward(value));
+ }
+#else
+ void InitOrAssign(const U& value) {
+ if (storage_.is_populated_)
+ storage_.value_ = value;
+ else
+ storage_.Init(value);
+ }
+#endif
+
+
+ void FreeIfNeeded() {
+ if (!storage_.is_populated_)
+ return;
+ storage_.value_.~T();
+ storage_.is_populated_ = false;
+ }
+
+ // For implementing conversion, allow access to other typed OptionalBase
+ // class.
+ template
+ friend class OptionalBase;
+
+ OptionalStorage storage_;
+};
+
+// The following {Copy,Move}{Constructible,Assignable} structs are helpers to
+// implement constructor/assign-operator overloading. Specifically, if T is
+// is not movable but copyable, Optional's move constructor should not
+// participate in overload resolution. This inheritance trick implements that.
+template
+struct CopyConstructible {};
+
+template <>
+struct CopyConstructible {
+ CONSTEXPR CopyConstructible() {}
+ CopyConstructible& operator=(const CopyConstructible&) { return *this; }
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ CONSTEXPR CopyConstructible(CopyConstructible&&) {}
+ CopyConstructible& operator=(CopyConstructible&&) { return *this; }
+#endif
+ private:
+ CONSTEXPR CopyConstructible(const CopyConstructible&);
+};
+
+template
+struct MoveConstructible {};
+
+template <>
+struct MoveConstructible {
+ CONSTEXPR MoveConstructible() {}
+ CONSTEXPR MoveConstructible(const MoveConstructible&) {}
+ MoveConstructible& operator=(const MoveConstructible&) { return *this; }
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ MoveConstructible& operator=(MoveConstructible&&) { return *this; }
+ private:
+ CONSTEXPR MoveConstructible(MoveConstructible&&);
+#endif
+};
+
+template
+struct CopyAssignable {};
+
+template <>
+struct CopyAssignable {
+ CONSTEXPR CopyAssignable() {}
+ CONSTEXPR CopyAssignable(const CopyAssignable&) {}
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ CONSTEXPR CopyAssignable(CopyAssignable&&) {}
+ CopyAssignable& operator=(CopyAssignable&&) { return *this; }
+#endif
+ private:
+ CopyAssignable& operator=(const CopyAssignable&);
+};
+
+template
+struct MoveAssignable {};
+
+template <>
+struct MoveAssignable {
+ CONSTEXPR MoveAssignable() {}
+ CONSTEXPR MoveAssignable(const MoveAssignable&) {}
+ MoveAssignable& operator=(const MoveAssignable&) { return *this; }
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ CONSTEXPR MoveAssignable(MoveAssignable&&) {}
+
+ private:
+ MoveAssignable& operator=(MoveAssignable&&);
+#endif
+};
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+// Helper to conditionally enable converting constructors and assign operators.
+template
+struct IsConvertibleFromOptional
+ : std::integral_constant<
+ bool,
+ std::is_constructible&>::value ||
+ std::is_constructible&>::value ||
+ std::is_constructible&&>::value ||
+ std::is_constructible&&>::value ||
+ std::is_convertible&, T>::value ||
+ std::is_convertible&, T>::value ||
+ std::is_convertible&&, T>::value ||
+ std::is_convertible&&, T>::value> {};
+
+template
+struct IsAssignableFromOptional
+ : std::integral_constant<
+ bool,
+ IsConvertibleFromOptional::value ||
+ std::is_assignable&>::value ||
+ std::is_assignable&>::value ||
+ std::is_assignable&&>::value ||
+ std::is_assignable&&>::value> {};
+
+// Forward compatibility for C++17.
+// Introduce one more deeper nested namespace to avoid leaking using std::swap.
+namespace swappable_impl {
+using std::swap;
+
+struct IsSwappableImpl {
+ // Tests if swap can be called. Check(0) returns true_type iff swap
+ // is available for T. Otherwise, Check's overload resolution falls back
+ // to Check(...) declared below thanks to SFINAE, so returns false_type.
+ template
+ static auto Check(int)
+ -> decltype(swap(std::declval(), std::declval()), std::true_type());
+
+ template
+ static std::false_type Check(...);
+};
+} // namespace swappable_impl
+template
+struct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check(0)) {};
+#endif
+} // namespace internal
+
+// On Windows, by default, empty-base class optimization does not work,
+// which means even if the base class is empty struct, it still consumes one
+// byte for its body. __declspec(empty_bases) enables the optimization.
+// cf)
+// https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
+#if defined(_WIN32)
+#define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
+#else
+#define OPTIONAL_DECLSPEC_EMPTY_BASES
+#endif
+
+// Optional is a Chromium version of the C++17 optional class:
+// std::optional documentation:
+// http://en.cppreference.com/w/cpp/utility/optional
+// Chromium documentation:
+// https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md
+//
+// These are the differences between the specification and the implementation:
+// - Constructors do not use 'constexpr' as it is a C++14 extension.
+// - 'constexpr' might be missing in some places for reasons specified locally.
+// - No exceptions are thrown, because they are banned from Chromium.
+// Marked noexcept for only move constructor and move assign operators.
+// - All the non-members are in the 'base' namespace instead of 'std'.
+//
+// Note that T cannot have a constructor T(Optional) etc. Optional checks
+// T's constructor (specifically via IsConvertibleFromOptional), and in the
+// check whether T can be constructible from Optional, which is recursive
+// so it does not work. As of Feb 2018, std::optional C++17 implementation in
+// both clang and gcc has same limitation. MSVC SFINAE looks to have different
+// behavior, but anyway it reports an error, too.
+template
+class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
+ : public internal::OptionalBase
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ , public internal::CopyConstructible::value>,
+ public internal::MoveConstructible::value>,
+ public internal::CopyAssignable::value &&
+ std::is_copy_assignable::value>,
+ public internal::MoveAssignable::value &&
+ std::is_move_assignable::value>
+#endif
+{
+ public:
+#undef OPTIONAL_DECLSPEC_EMPTY_BASES
+
+ typedef T value_type;
+
+ // Defer default/copy/move constructor implementation to OptionalBase.
+ CONSTEXPR Optional() {}
+ CONSTEXPR Optional(const Optional& other) : internal::OptionalBase(other) {}
+
+ CONSTEXPR Optional(nullopt_t) {} // NOLINT(runtime/explicit)
+
+ // Converting copy constructor. "explicit" only if
+ // std::is_convertible::value is false. It is implemented by
+ // declaring two almost same constructors, but that condition in enable_if_t
+ // is different, so that either one is chosen, thanks to SFINAE.
+ template
+ Optional(const Optional& other) : internal::OptionalBase(other) {}
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ // Converting move constructor. Similar to converting copy constructor,
+ // declaring two (explicit and non-explicit) constructors.
+ template
+ Optional(Optional&& other) : internal::OptionalBase(std::move(other)) {}
+
+ template
+ CONSTEXPR explicit Optional(in_place_t, Args&&... args)
+ : internal::OptionalBase(in_place, std::forward(args)...) {}
+
+ template
+ CONSTEXPR explicit Optional(in_place_t,
+ std::initializer_list il,
+ Args&&... args)
+ : internal::OptionalBase(in_place, il, std::forward(args)...) {}
+#else
+ CONSTEXPR explicit Optional(in_place_t, const T& _value)
+ : internal::OptionalBase(in_place, _value) {}
+ template
+ CONSTEXPR explicit Optional(in_place_t,
+ const U il[],
+ const T& _value)
+ : internal::OptionalBase(in_place, il, _value) {}
+#endif
+
+ // Forward value constructor. Similar to converting constructors,
+ // conditionally explicit.
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ template
+ CONSTEXPR Optional(U&& value)
+ : internal::OptionalBase(in_place, std::forward(value)) {}
+#else
+ template
+ CONSTEXPR Optional(const U& value)
+ : internal::OptionalBase(in_place, value) {}
+#endif
+
+ ~Optional() {}
+
+ // Defer copy-/move- assign operator implementation to OptionalBase.
+ Optional& operator=(const Optional& other) {
+ if (&other == this) {
+ return *this;
+ }
+
+ internal::OptionalBase::operator=(other);
+ return *this;
+ }
+
+ Optional& operator=(nullopt_t) {
+ FreeIfNeeded();
+ return *this;
+ }
+
+ // Perfect-forwarded assignment.
+ template
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ Optional& operator=(U&& value) {
+ InitOrAssign(std::forward(value));
+ return *this;
+ }
+#else
+ Optional& operator=(const U& value) {
+ InitOrAssign(value);
+ return *this;
+ }
+#endif
+
+ // Copy assign the state of other.
+ template
+ Optional& operator=(const Optional& other) {
+ CopyAssign(other);
+ return *this;
+ }
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ // Move assign the state of other.
+ template
+ Optional& operator=(Optional&& other) {
+ MoveAssign(std::move(other));
+ return *this;
+ }
+#endif
+
+ const T* operator->() const {
+ return &storage_.value_;
+ }
+
+ T* operator->() {
+ return &storage_.value_;
+ }
+
+ const T& operator*() const {
+ return storage_.value_;
+ }
+
+ T& operator*() {
+ return storage_.value_;
+ }
+
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ CONSTEXPR explicit operator bool() const { return storage_.is_populated_; }
+#else
+ CONSTEXPR operator bool() const { return storage_.is_populated_; }
+#endif
+
+ CONSTEXPR bool has_value() const { return storage_.is_populated_; }
+
+#if 1
+ const T& value() const {
+ return storage_.value_;
+ }
+
+ template
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ CONSTEXPR T value_or(U&& default_value) const {
+ // TODO(mlamouri): add the following assert when possible:
+ // static_assert(std::is_copy_constructible::value,
+ // "T must be copy constructible");
+ static_assert(std::is_convertible::value,
+ "U must be convertible to T");
+ return storage_.is_populated_
+ ? value()
+ : static_cast(std::forward(default_value));
+ }
+#else
+ CONSTEXPR T value_or(const U& default_value) const {
+ return storage_.is_populated_
+ ? value()
+ : static_cast(default_value);
+ }
+#endif
+#else
+ const T& value() const & {
+ return storage_.value_;
+ }
+
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ const T&& value() const && {
+ return std::move(storage_.value_);
+ }
+#endif
+
+ template
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ CONSTEXPR T value_or(U&& default_value) const & {
+ // TODO(mlamouri): add the following assert when possible:
+ // static_assert(std::is_copy_constructible::value,
+ // "T must be copy constructible");
+ static_assert(std::is_convertible::value,
+ "U must be convertible to T");
+ return storage_.is_populated_
+ ? value()
+ : static_cast(std::forward