//
//  LVRTCEngine.h
//  LVRTCEngine
//
//  Copyright © 2021年 LinkV. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LVRTCEngineDefines.h"
#if TARGET_OS_IOS
#import <ReplayKit/ReplayKit.h>
#endif

NS_ASSUME_NONNULL_BEGIN

@class LVRTCEngine;
@class LVRTCEngineDelegate;

#pragma mark -
#pragma mark - LVRTCEngineDelegate

LV_EXPORT_CLASS

/// 音视频引擎代理回调方法
@protocol LVRTCEngineDelegate <NSObject>
@required

/// 房间重连成功通知，SDK 在网络断开和恢复时会自动进行重连，重连结果通过该回调通知 APP
- (void)OnRoomReconnected;

/// 加入房间成功的回调
/// @param code 加入房间是否成功错误码
/// @param users 用户列表，如果房间中有用户存在，该列表会自动生效
- (void)OnEnterRoomComplete:(LVErrorCode)code users:(nullable NSArray<LVUser*>*)users;

/// 退出房间完成，异常退出和用户主动调用 logoutRoom 方法会触发该回调方法
- (void)OnExitRoomComplete;

/// 房间断开的通知，网络异常时 SDK 会自动进行重连，90 秒如果重连失败会触发该方法回调
/// @param code 错误码
- (void)OnRoomDisconnected:(LVErrorCode)code;

/// 有成员加入的通知
/// @param user 成员列表
- (void)OnAddRemoter:(LVUser *)user;

/// 有成员离开的通知
/// @param uid 离开用户 ID
- (void)OnDeleteRemoter:(NSString*)uid;

/// 远端混流完成的回调，用户可以通过调用混乱方法在远端进行音视频混流，参考 mixStream
/// @param code 混流结果
- (void)OnMixComplete:(LVErrorCode)code;

/// 单路音频流回调
/// @param uid 该路音频的用户 ID
/// @param audio_data 音频数据
/// @param bits_per_sample PCM 位深
/// @param sample_rate 采样率
/// @param number_of_channels 通道数
/// @param number_of_frames 帧数量
- (void)OnAudioData:(NSString *)uid
         audio_data:(const void*)audio_data
    bits_per_sample:(int)bits_per_sample
        sample_rate:(int)sample_rate
 number_of_channels:(size_t)number_of_channels
   number_of_frames:(size_t)number_of_frames;

/// 混音录音数据回调，该方法需要打开录音功能才会触发回调 setAudioRecordFlag:
/// @param data pcm 数据
/// @param samples 数据长度
/// @param nchannel 通道数据
/// @param samplesPerChannel 每声道采样数
/// @param flag 类型
- (void)OnAudioMixStream:(const int16_t *)data samples:(int)samples nchannel:(int)nchannel samplesPerChannel:(int)samplesPerChannel flag:(LVAudioRecordType)flag;


/// 发布资源质量状态变化的通知，SDK 内部会定时统计推流的质量信息，APP 可以实现该方法获取推流的视频质量信息统计，回调的频率可以通过 +setPublishQualityMonitorCycle 进行设置
/// @param quality 质量信息
- (void)OnPublishQualityUpdate:(LVVideoStatistic *)quality;

/// 播放质量变化的通知，SDK 内部会定时统计拉流质量信息，APP 可以实现该方法获取拉流的视频质量信息统计，回调的频率可以通过 +setPlayQualityMonitorCycle 进行设置
/// @param quality 质量信息
/// @param userId 用户 ID
- (void)OnPlayQualityUpate:(LVVideoStatistic *)quality userId:(NSString*)userId;

/// 发布资源状态变更的通知，调用 startPublishing 之后会触发该方法回调，发布资源状态的变更会通过该方法进行通知
/// @param code 状态码
- (void)OnPublishStateUpdate:(LVErrorCode)code;

/// 播放状态变化的通知，调用 startPlayingStream: 方法之后，播放状态的变更会通过该方法进行通知
/// @param code 状态码
/// @param userId 用户 ID
- (void)OnPlayStateUpdate:(LVErrorCode)code userId:(NSString*)userId;

/// 远端用户音量变化的通知，该回调通需要调用打开音量变化监听方法才会生效 startSoundLevelMonitor，该回调频率可以调用 startSoundLevelMonitor:
/// @param soundLevels 远端用户音量信息
- (void)OnAudioVolumeUpdate:(NSArray<LVAudioVolume *> *)soundLevels;

@optional
/// 是否需要在视频帧上附加其他媒体信息
/// @param timestamp 当前要发送数据帧的时间戳
/// @return 请返回要随当前视频帧发送的附加数据 （字符串最长长度 24 个字符）
-(NSString *)OnMediaSideInfoInPublishVideoFrame:(NSUInteger)timestamp;

/// 收到远端视频数据回调，如果为 SDK 设置了渲染视图，SDK 内部会自动将该视频帧渲染出来
/// @param pixelBuffer 已解码的视频数据
/// @param uid 用户 ID
/// @param sei 随视频数据携带的附加数据信息
/// @return 建议返回当前渲染完成的时间戳，用以统计渲染延迟
/// @discussion 注：如果用户实现该接口，则 SDK 内部的远端视频渲染会自动实现，渲染完全由外部进行实现
- (int64_t)OnDrawFrame:(CVPixelBufferRef)pixelBuffer
                   uid:(NSString *)uid
                   sei:(NSString *)sei;

/// SDK 内部采集数据回调
/// @param videoFrame 视频原始数据
/// @return 处理后的视频数据，SDK 内部不会调用 CFRetain 增加引用计数， 会调用 CFRelease 减少引用计数， 视频开发者创建的视频对象， 原样返回则不做任何处理
-(CMSampleBufferRef)OnCaptureVideoFrame:(CMSampleBufferRef)videoFrame;


/// 视频美颜回调
/// @param pixelBuffer 颜色缓冲区逻辑
-(void)OnCaptureVideoBuffer:(CVPixelBufferRef)pixelBuffer;

/// 用户被踢出房间
/// @param reason 被踢原因
/// @param roomId 房间号
- (void)OnKickOff:(NSInteger)reason roomId:(NSString *)roomId;

/// 混音播放器当前播放时长
/// @param time_ms 播放时长
- (void)AudioMixerCurrentPlayingTime:(int)time_ms;

/// 混音播放器当前音频播放结束
- (void)AudioMixerPlayerDidFinished;


/// 收到视频首帧回调通知事件
/// @param userId 视频发送者用户 ID
/// @param streamId 流 ID，默认为空字符串，如果使用自定义视频流时为自定义视频流对应的流名称
- (void)OnReceivedFirstVideoFrame:(NSString *)userId streamId:(NSString *)streamId;


/// 收到音频首帧回调通知事件
/// @param userId 音视频发送者用户 ID
/// @param streamId 流 ID，默认为空字符串，如果使用自定义视频流时为自定义视频流对应的流名称
- (void)OnReceivedFirstAudioFrame:(NSString *)userId streamId:(NSString *)streamId;

@end


#pragma mark -
#pragma mark - LVRTCEngine

LV_EXPORT_CLASS

/// RTC 引擎服务主类，音视频基本功能通过该类提供
@interface LVRTCEngine : NSObject

/// 不能直接使用，请通过 sharedInstance 获取该实例
/// @warning 不能直接使用
+(instancetype) alloc __attribute__((unavailable("alloc not available, call sharedInstance instead")));

/// 不能直接使用，请通过 sharedInstance 获取该实例
/// @warning 不能直接使用
-(instancetype) init __attribute__((unavailable("init not available, call sharedInstance instead")));

/// 不能直接使用，请通过 sharedInstance 获取该实例
/// @warning 不能直接使用
+(instancetype) new __attribute__((unavailable("new not available, call sharedInstance instead")));

/// LVRTCEngine SDK 版本号（1.0.1）
/// @return 版本号
/// @discussion 开发者使用本 API 获取 SDK 版本号
+ (NSString *)versionName;

/// LVRTCEngine SDK 版本号，数字（10001）
/// @return 版本号
/// @discussion 开发者使用本 API 获取 SDK 版本号
+ (NSInteger)versionNumber;

/// SDK 内部版本号，汇报给 linkv 时可以提供该版本号
+ (NSString *)buildVersion;

/// 初始化 SDK
+ (void)initSdk;

/// 卸载 SDK，销毁单例对象资源
+ (void)unInitSDK;

/// 设置 ISO 国家码, 辅助调度信息.
/// @param iso iso 国家码参数
+ (void)setISOCountryCode:(NSString *)iso;

/// 设置推流时数据统计信息回调的频率，回调方法请看 OnPublishQualityUpdate 回调
/// @param sec 回调频率（1 / sec）
+ (void)setPublishQualityMonitorCycle:(int)sec;

/// 设置拉流时数据统计信息回调的频率，回调方法请看 OnPlayQualityUpate 回调
/// @param sec 回调频率（1 / sec）
+ (void)setPlayQualityMonitorCycle:(int)sec;

/// 设置日志打印级别（SDK 日志保存在缓存目录的 cmliveroom 目录下）
/// @param level 日志打印级别
+ (void)setLogLevel:(LVLoggingSeverity)level;

+ (void)setLogLevel:(LVLoggingSeverity)level dir:(NSString *)dir;

/// 是否使用测试环境
/// @param env YES 为使用测试环境，NO 为不使用测试环境（默认为 NO）
+ (void)setUseTestEnv:(bool)env;

/// 设置调试的 signal  IP 地址
/// @param ip signal IP 地址
+ (void)setDebugServerIp:(NSString *)ip;

/// 设置接收到视频数据时解码的像素格式类型
/// @param osType 像素格式类型（CVPixelFormatType），VideoToolBox 解码器支持的颜色像素类型
+ (bool)setDecoderPixelType:(OSType)osType;

/// 设置视频数据编码的像素格式类型
/// @param osType 像素格式类型（CVPixelFormatType），VideoToolBox 编码器支持的颜色像素类型
+ (bool)setEncoderPixelType:(OSType)osType;

+ (void)setIosScreenRecord:(BOOL)isScreenRecord;
/// 返回 LVRTCEngine 实例对象
+ (instancetype)sharedInstance;


/// SDK 鉴权
/// @param appId 向 LiveMe 申请的 appId
/// @param skStr  SDK 签名字符串
/// @param userId 用户 ID
/// @param completion 鉴权完成回调
- (void)auth:(NSString *)appId
       skStr:(NSString *)skStr
      userId:(NSString *)userId
  completion:(LVServiceCompletion)completion;


/// 设置视频编码参数
/// @param config 编码参数配置
/// @discussion 注：如果后面设置的视频采集分辨率大于之前设置的分辨率，摄像头可能会进行重庆操作
- (void)setAVConfig:(LVAVConfig *)config;

/// 获取当前视频编码参数
/// @return 视频编码参数
- (LVAVConfig *)getAVConfig;


/// 加入音视频房间（音视频会议）
/// @param userId 用户 ID
/// @param roomId 房间 ID
/// @param isHost 是否是主持人
/// @param isOnlyAudio 是否以音频模式加入
/// @param delegate 房间回调代理
- (void)loginRoom:(NSString *)userId
           roomId:(NSString *)roomId
           isHost:(bool)isHost
      isOnlyAudio:(bool)isOnlyAudio
         delegate:(id<LVRTCEngineDelegate>)delegate;

/// 退出房间
/// @param completion 离开房间结果回调
- (void)logoutRoom:(LVServiceCompletion)completion;

/// 开始远端视频混流（将多路视频流混合在一个视频流中），混流成功与否通过 OnMixComplete 回调告知
/// @param config 混乱配置
- (bool)mixStream:(LVMixStreamConfig*)config;

/// 停止混流
- (void)stopMixStream;

/// 发布音视频数据（推流），如果登录房间时 isOnlyAudio 为 YES 则只发送音频数据，视频数据不发送，推流状态的变更通过 OnPublishStateUpdate: 回调
- (bool)startPublishing;

/// 停止发布音视频数据
- (void)stopPublishing;

/// 开始播放一路音视频流，播放状态的变更通过 OnPlayStateUpdate:userId: 回调
/// @param userId 要播放的音视频流用户 ID
- (void)startPlayingStream:(NSString *)userId;

/// 停止播放一路音视频流
/// @param userId 要停止播放的音视频流用户 ID
- (void)stopPlayingStream:(NSString *)userId;

/// 房间之间 PK（跨房间连麦功能）
/// @param roomId 房间 ID
- (void)linkRoom:(NSString *)roomId;

/// 取消跨房间连麦功能
/// @param roomId 房间 ID
- (void)unlinkRoom:(NSString *)roomId;

/// 房间之间 PK（跨房间连麦功能）
/// @param roomId 房间 ID
/// @param linkUserId PK 对象的 userId
- (void)linkRoom:(NSString *)roomId linkUserId:(NSString *)linkUserId;

/// 取消跨房间连麦功能
/// @param roomId 房间 ID
/// @param unlinkUserId 取消 pk 对象的 userId
- (void)unlinkRoom:(NSString *)roomId unlinkUserId:(NSString *)unlinkUserId;


/// 开始视频采集
-(void)startCapture;

/// 停止视频采集
-(void)stopCapture;

/// 摄像头状态获取
-(bool)cameraIsRunning;

/// 切换摄像头
/// @param position 摄像头位置
-(void)switchCamera:(LVRTCCameraPosition)position;

/// 为音视频设置预览视图，请先加入房间后再进行设置，SDK 内部会自动将视图和接收到的音视频数据进行绑定操作
/// @param view 视图信息
/// @discussion 如果不传 uid 则该视图默认为当前登录用户
-(void)addDisplayView:(LVRTCDisplayView *)view;

/// 移除预览视图
/// @param view 视图信息
-(void)removeDisplayView:(LVRTCDisplayView *)view;

/// 开启或关闭麦克风
/// @param enbale true 开启，false 关闭（默认为 true）
/// @return true 成功，false 失败
/// @discussion 推流时可调用本 API 进行参数配置
- (bool)enableMic:(bool)enbale;

/// 扬声器和听筒切换功能，需要在通话场景下设置才能生效
/// @param enable true 视同扬声器播放音频，false 使用听筒播放音频。（默认 true）
/// @return true 成功，false 失败
- (bool)enableSpeakerphone:(bool)enable;

/// 声音数据回调参数设置，支持多种录制模式，录制结果通过 OnAudioMixStream: samples:nchannel:nchannel flag: 回调
/// @param flag 参考 CMAudioRecodType, 默认 CMAudioRecodTypeNone 标识不回调
- (void)setAudioRecordFlag:(LVAudioRecordType)flag;

/// 开启音量变化监听，并设置音量变化监听回调频率，成功后回调 OnAudioVolumeUpdate:
/// @param timeInMS 单位毫秒（默认回调频率为 100 ms 回调一次）
- (void)startSoundLevelMonitor:(int)timeInMS;

/// 停止音量变化的监听
- (void)stopSoundLevelMonitor;

/// 获取用户的音量信息
/// @param userId 用户 ID
/// @return 用户 ID 对应的音量数据
- (int)getSoundLevelByUserId:(NSString *)userId;

/// 设置是否允许 SDK 自动根据设备的方向调整视频的输出方向
/// @param enable 打开和关闭（默认是 YES）
-(void)enableVideoAutoRotation:(bool)enable;

/// 设置手动管理视频输出方向，该方法需要先调用 enableVideoAutoRotation，将自动旋转方法关闭才能生效
/// @param orientation 视频输出方向，（默认是 LVImageOrientationNone ）
-(void)setOutputVideoOrientation:(LVImageOrientation)orientation;

/// 设置视图旋转方向
/// 注：调用 setOutputVideoOrientation， setOutputVideoRotation 会改变摄像头数据输出方向，导致本地渲染方向不准确，需要加以反方向进行处理才准确
/// 在横竖屏切换时由于视图方向发生变化，需要旋转视图旋转内容才能适配
/// @param rotation 视图旋转方向
-(void)setDisplayViewRotation:(LVVideoRotation) rotation;

/// 开始播放音乐文件及混音（声音伴奏）
/// @param filePath 文件路径
/// @param mode LVAudioMixingMode，设置混音模式
/// @param loop 指定音频文件循环播放的次数，正整数：循环的次数 -1：无限循环
/// @return 0 ： 方法调用成功，!0：失败
-(int)startAudioMixing:(NSString*)filePath mode:(LVAudioMixingMode)mode loop:(int)loop;

/// 动态调整混音模式
/// @param mode 混音模式参数
-(void)setAudioMixingMode:(LVAudioMixingMode)mode;

/// 停止播放音乐文件及混音。请在房间内调用该方法。
/// @return 0：方法调用成功 !0：方法调用失败
-(int)stopAudioMixing;

/// 暂停播放音乐文件及混音。请在房间内调用该方法。
/// @return 0：方法调用成功 !0：方法调用失败
-(int)pauseAudioMixing;

/// 恢复播放音乐文件及混音。请在房间内调用该方法。
/// @return 0：方法调用成功 !0：方法调用失败
-(int)resumeAudioMixing;

/// 获取当前伴奏音量，请在伴奏开始后调用
/// @return -1：伴奏未开始 0～100：当前伴奏音量
-(int)getAudioMixingVolume;

/// 调节音乐文件的播放音量。请在房间内调用该方法。
/// @param volume 音量：0～100
/// @return 0：方法调用成功 !0：方法调用失败
-(int)adjustAudioMixingVolume:(int)volume;

/// 获取当前伴奏文件总时长，单位毫秒。请在房间内调用该方法。
/// @return 文件长度
-(long)getAudioMixingTotalLength;

/// 获取音乐文件的播放进度。单位为毫秒。请在房间内调用该方法。
/// @return <0：方法调用失败 >=0：方法调用成功并返回伴奏播放进度
-(long)getAudioMixingCurrentPosition;

/// 设置音乐文件的播放位置。请在房间内调用该方法。
/// @param pos 整数。进度条位置，单位为毫秒
/// @return 0：方法调用成功 !0：方法调用失败
-(long)setAudioMixingPosition:(int)pos;

/// 设置外置音频数据参数
/// @param audioConfig 音频参数
-(void)setExternalAudioConfig:(LVExternalAudioConfig *)audioConfig;

/// 获取当前外置音频参数
/// @return 外置音频参数
-(LVExternalAudioConfig *)getExternalAudioConfig;

/// 打开和关闭外置音频采集功能，该参数如果打卡会自动将 SDK 内置麦克风功能禁用，由用户向 SDK 输入音频 PCM 数据。请在加入房间之前设置
/// @param enable true: 打卡，false: 关闭
-(void)enableExternalAudioInput:(bool)enable;

/// 发送外置音频数据，注：只有调用 enableExternalAudioInput 打开外部音频输入接口之后才会生效
/// @param audioFrameBuffer 音频数据
/// @param length 音频数据长度（int16_t 数组数据长度，切记不是 buffer 缓冲区的长度）
/// @return 发送成功与否
-(int)sendAudioFrame:(int16_t *)audioFrameBuffer length:(int)length;

/// 发送外部 app 音频数据
/// @param audioBuffer 音频数据
/// @param length 音频数据长度，int16 长度
/// @param channel 通道数据
/// @param samplerate 采样率
/// @param volume 音量
-(int)sendAppAudioFrame:(int16_t *)audioBuffer length:(int)length channel:(int)channel samplerate:(int)samplerate volume:(int)volume;
/// 外部采集的视频数据（可以随视频附加其他信息） 注：调用 startCapture 后该方法会被忽略，使用该方法发送视频时不会自动绘制 sampleBuffer 到本地的 LVRTCDisplayView，需要开发者自行实现视图渲染功能，或者调用 sendVideoFrame:sei:type: 使用 SDK 内部渲染
/// @param sampleBuffer 视频数据（必须是 YUV 或者 RGBA 的视频数据）
/// @see startCapture
- (void)sendVideoFrame:(CMSampleBufferRef)sampleBuffer;

/// 外部采集的视频数据（可以随视频附加其他信息)   注：调用 startCapture 后该方法会被忽略，使用该方法发送视频时不会自动绘制 sampleBuffer 到本地的 LVRTCDisplayView，需要开发者自行实现视图渲染功能，或者调用 sendVideoFrame:sei:type: 使用 SDK 内部渲染
/// @param sampleBuffer 视频数据（必须是 YUV 或者 RGBA 的视频数据）
/// @param sei 媒体附加数据，该数据会随视频一起发送到接收端
/// @see startCapture
- (void)sendVideoFrame:(CMSampleBufferRef)sampleBuffer sei:(NSString*)sei;

/// 外部采集的视频数据（可以随视频附加其他信息）   注：调用 startCapture 后该方法会被忽略，
/// @param sampleBuffer 视频数据（必须是 YUV 或者 RGBA 的视频数据）
/// @param sei 媒体附加数据，该数据会随视频一起发送到接收端
/// @param type 媒体类型
- (void)sendVideoFrame:(CMSampleBufferRef)sampleBuffer sei:(NSString*)sei type:(LVSampleBufferType)type;

#if TARGET_OS_IOS
-(void)setAssetWriter:(AVAssetWriter *) assetWriter;
- (void)setReplaykitOrientation:(CGImagePropertyOrientation) orientation;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
- (void)sendReplaykitSample:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType;
#pragma clang diagnostic pop
#endif

-(void)handleVideoFrame:(CMSampleBufferRef)cameraBuffer rotation:(LVVideoRotation)rotation isFaceCamera:(BOOL)isFaceCamera;

/// 控制远端音频流音量, 加入房间成功后调用
/// @param volume 音量大小（0，100）
/// @param userId 被控制的用户ID
- (void)setPlayVolume:(int)volume userId:(NSString *)userId;


/// 控制所有远端音频流音量, 加入房间成功后调用
/// @param volume 音量大小（0，100）
- (void)setPlayVolume:(int)volume;

/// 设置回声消除音频模式
/// @param mode 模式参数
- (void)setAecMode:(LVAudio3AMode)mode;

/// 设置降噪模式
/// @param mode 模式参数
- (void)setNsMode:(LVAudio3AMode)mode;

/// 设置自动增益模式
/// @param mode 模式参数
- (void)setAgcMode:(LVAudio3AMode)mode;

/// SDK 内部录制功能，目前仅支持视频编码为 H264、音频编码为 Opus 的录制，录制格式为 mkv 文件，无论录制音频还是视频请提供 mkv 后缀文件地址, eg: /tmp/recorder/hello.mkv
/// @param userId 用户 ID
/// @param path 文件路径
/// @param type 音视频录制类型
/// @return 0 : 录制成功， 其他 : 录制失败
- (int)startRecorder:(NSString*)userId path:(NSString *)path type:(LVRecorderType)type;

/// 停止录制，非 LVRecorderType_External 录制类型 compltion 的 URL 为空字符串，请使用录制时传的视频文件路径
/// @param userId 音视频用户 ID
/// @param completion 录制完成回调
/// @return 0 : 停止录制成功，其他 : 停止录制失败
- (int)stopRecorder:(NSString*)userId;

@end


@protocol LVRTCRecorderCallback <NSObject>

/// 视频上传完成回调
/// @param taskId 任务 ID
/// @param thumbnailImages 视频缩略图地址 [{"time":213232, "image":"http://linkv.sg/loom/32324343.jpg"},{"time":213232, "image":"http://linkv.sg/loom/3232434113.jpg"}]
/// @param url 视频远端 URL
/// @param duration 录制时长(ms)
/// @param size 文件大小
/// @param encode_width 视频编码宽度
/// @param encode_height 视频编码高度
-(void)OnVideoDidUploadCompletion:(NSString *)taskId thumbnailImages:(NSArray *)thumbnailImages url:(NSString *)url duration:(int)duration size:(long long)size encode_width:(int)encode_width encode_height:(int)encode_height rotate:(int)rotate code:(int)code;

/// 上传完成进度
/// @param taskId videoId
/// @param persent 上传百分比
-(void)OnUploadPersent:(NSString *)taskId persent:(int)persent;

/// 音频录制设备发生变化
/// @param newAudioDevices 音频设备信息，参考 GetAudioCaptureDevice
-(void)OnAudioDeviceChanged:(NSArray *)newAudioDevices;


/// 视频录制设备发生变化
/// @param newVideoDevices 视频设备信息，参考 GetVideoCaptureDevice
-(void)OnVideoDeviceChanged:(NSArray *)newVideoDevices;


/// 音量变换回调
/// @param volume 音量信息
-(void)OnAudioVolume:(int)volume;


/// 接收到远端发送过来的画中画数据，需要打开画中画功能
/// @param sampleBufferRef 画中画内容
-(void)didReceivePictureInPictureCMSampleBufferRef:(CMSampleBufferRef)sampleBufferRef;

/// 画中画错误码
/// @param code 错误码， 1 为客户端发送超时，3 为客户端无 Wi-Fi 网络断开， 4 客户端连上服务端
-(void)didReceivePictureInPictureException:(int)code;

/// 收到一条画中画消息
/// @param message 消息内容
/// @param fromClient YES 表示该消息由客户端发送过来，NO 表示该消息表示该消息由服务端发送过来
-(void)didReceivePictureInPictureMessage:(NSString *)message fromClient:(BOOL)fromClient;

/// 系统是否正在播放声音
/// @param isPlaying YES 表示当前系统正在使用扬声器播放声音，NO 表示没有在使用扬声器播放声音
-(void)OnSystemAudioStateChanged:(int)isPlaying;

@end


@interface LVRTCEngine (CloudRecorder)

/// 开启视频分片录制功能，录制视频文件保存到云端
/// @param taskId taskId 视频录制任务 ID
/// @param videoPrefix  视频远端目前前缀
/// @param imagePrefix  图片远端目录前缀
/// @param imageInterval  图片录制间隔
/// @param type 录制文件类型
- (int)startRecorder:(NSString*)taskId
         videoPrefix:(NSString *)videoPrefix
         imagePrefix:(NSString *)imagePrefix
       imageInterval:(NSInteger)imageInterval
                type:(LVRecorderType)type;

/// 开启视频分片录制功能，录制视频文件保存到云端
/// @param taskId taskId 视频录制任务 ID
/// @param videoPrefix  视频远端目前前缀
/// @param imagePrefix  图片远端目录前缀
/// @param imageInterval  图片录制间隔
/// @param withSystemAudio 是否录制系统声音
/// @param type 录制文件类型
- (int)startRecorder:(NSString*)taskId
         videoPrefix:(NSString *)videoPrefix
         imagePrefix:(NSString *)imagePrefix
       imageInterval:(NSInteger)imageInterval
                type:(LVRecorderType)type
     withSystemAudio:(bool)withSystemAudio;


/// 停止视频录制，录制结果会通过录制回调返回
- (bool)stopRecorder;

- (bool)stopRecorderSync;

- (void)pauseRecorder;

- (void)resumeRecorder;

- (void)removeTask:(NSString*)taskId;

/// 设置视频录制参数以及回调
/// @param presignUrl 视频上传鉴权地址
/// @param token 鉴权 token
/// @param localDir 本地视频临时存储路径
/// @param callback 录制完成回调
- (void)setRecorderConfig:(NSString *)presignUrl
                    token:(NSString *)token
                 localDir:(NSString *)localDir
                      uid:(NSString *)uid
                 callback:(id<LVRTCRecorderCallback>)callback;

- (void)OnTsVideoGenerated:(NSString *)path
                    filename:(NSString *) filename
                    taskId:(NSString *) taskId
                    duration:(float)duration
                    isM3u8: (bool) isM3u8;
- (void)uploadHistoryTask;


/// 设置美颜参数
/// @param enable 打开美颜功能
/// @param beautyLevel 美颜级别 0 -- 2
/// @param brightLevel 亮度级别 0 -- 1
/// @param toneLevel 色调级别 0 -- 1
-(void)SetBeautyParameter:(BOOL)enable beautyLevel:(float)beautyLevel brightLevel:(float)brightLevel toneLevel:(float)toneLevel;


/// 设置录制失败汇报 url
/// @param url 录制失败汇报 url
-(void)SetRecorderFailedUrl:(NSString *)url;


-(void)SetCameraMetalSpeedupEnable:(bool)enable;

/// 开启画中画功能服务端，返回值为当前机器可用的 Wi-Fi 局域网 IP，接收到的视频数据通过 didReceivePictureInPictureCMSampleBufferRef 回调返回
/// 返回值为服务地址，长度大于 0 是成功
-(NSString *)startPictureInPictureServer;

// 关闭 PiP 服务端
-(void)stopPictureInPictureServer;

/// 开启画中画客户端，serverUrl 为服务端接口的返回值
/// 返回值为开启成功或失败， 0 成功， 其他失败； 3 无效的 Wi-Fi 网络
-(int)startPictureInPictureClient:(NSString *)serverUrl;

/// 关闭 PiP 客户端
-(void)stopPictureInPictureClient;

/// 发送画中画消息
/// @param message 画中画消息内容（消息长度需大于等于 8 位，小于等于 16 位）
/// @param isClient YES 是客户端发送给服务端， NO 是服务端发送给客户端
-(void)sendPictureInPictureMessage:(NSString *)message isClient:(BOOL)isClient;

/// 视频裁剪功能，视频在录制过程中可以进行裁剪，裁剪精度上下误差 4 秒钟
/// @param start 裁剪开始时间（从开始录制开始算起）
/// @param end 采集结束时间（从开始录制算起）
/// @param clipTaskId 裁剪视频 ID，该视频裁剪成功后会通过视频录制完成接口进行回调
/// 0 获取视频成功， 1 获取失败失败；（注：如果未在进行视频录制中 sdk 不会报失败，需业务层自行处理）
-(int)GetClipVideo:(int64_t)start end:(int64_t)end clipTaskId:(NSString *)clipTaskId;


/// 设置视频录制编码相关参数
/// @param short_side 视频短边，SDK 会自动匹配长边
/// @param framerate 视频帧率
/// @param bitrate 视频码率（单位 kbps）
-(int)SetRecorderAVConfig:(int)short_side framerate:(int)framerate bitrate:(int)bitrate;

/// 开启音频录制
- (void)StartAudioRecording;

/// 结束音频录制
- (void)StopAudioRecording;


- (void)AddImageTicker;

@end

#if TARGET_OS_OSX


@protocol LVRTCScreenCaptureCallback <NSObject>

/// macOS 屏幕共享录制回调
/// @param buffer BGRA 视频数据
/// @param size buffer 长度
/// @param width 视频宽度
/// @param height 视频高度
/// @param timestamp_us 视频采集时间戳
-(void)OnCaptureScreenVideoFrame:(uint8_t *)buffer size:(int)size width:(int)width height:(int)height timestamp_us:(int64_t)timestamp_us;

@end


@interface LVRTCEngine (ScreenRecorder_macOS)

/// 设置屏幕采集数据回调
/// @param callback 回调代理
-(void)SetScreenCaptureCallback:(id<LVRTCScreenCaptureCallback>)callback;

/// 初始化屏幕采集功能，默认采集 720P 视频内容，如果为 Region，则 frame 默认为全屏 frame
/// @param type 采集类型
-(void)InitCapture:(LVDesktopCaptureType)type;

/// 初始化屏幕采集功能
/// @param type 屏幕采集类型
/// @param size 采集视频大小
/// @param frame 区域采集时自定义采集视频位置
-(void)InitCapture:(LVDesktopCaptureType)type size:(CGSize)size frame:(CGRect)frame;

/// 初始化摄像头，该接口调用后摄像头以对应参数进行采集
/// @param cameraGuid 摄像头ID
/// @param colorFormat 颜色格式
/// @param width 视频宽
/// @param height 视频高
-(void)InitCameraCapture:(NSString *)cameraGuid colorFormat:(NSString *)colorFormat width:(int)width height:(int)height;

/// 获取设备支持摄像头列表
-(NSArray<NSDictionary *> *)GetVideoCaptureDevice;

/// 获取设备支持麦克风列表
-(NSArray *)GetAudioCaptureDevice;

/// 设置音频采集设备
/// @param index index
-(void)SetRecordingDevice:(NSString *)index;

/// 打开音频插件安装程序
- (bool)OpenPluginApp:(NSString *)driverPath shellPath:(NSString *)shellPath;

/// 获取摄像头支持分辨率
/// @param cameraName 摄像头名称
-(NSArray<NSValue *> *)GetCameraResolution:(NSString *)cameraName;

/// 获取对应摄像头名称支持的颜色格式
-(NSArray<NSString *> *)GetCameraColorType:(NSString *)cameraName;

/// 开启屏幕采集，请在 InitCapture 之后跳用
/// @param sourceId  窗口 ID 或者屏幕 ID
/// @param framerate 采集帧率
-(bool)StartScreenCapture:(long)sourceId framerate:(int)framerate;

/// 停止采集
-(void)StopScreenCapture;

/// 获取窗口里表信息
-(NSArray *)GetWindowsList:(int)type;

/// 获取某个屏幕下的所有窗口信息
/// @param screenId 屏幕 ID
-(NSArray *)GetWindowsListGroupBy:(long)screenId;

/// 对当前所有窗口进行截图
/// @param sourceIdList 创建 ID 列表
/// @param type 截图类型
-(NSArray<LVImage *> *)SnapshotWindows:(NSArray *)sourceIdLis type:(int)type;

/// 打开或关闭光标采集
/// @param enable  true 打开；false 关闭
- (void)SetMouseCursorEnable:(bool)enable;

/// 移除某一个视图
/// @param enable YES 为打开，NO 为关闭，需配合 electron 窗口保护功能使用
- (void)SetExcludedWindowEnable:(bool)enable;

/// 停止 adb
- (void)StopAudioDeviceModule;

/// 是否使用默认分辨率
/// @param use true 为使用，false 为不使用
- (void)SetUseDefaultResultion:(bool)use;

/// 上传因视频日志
- (void)UploadLog;

/// 开启系统声音录制
/// @param enable  true 为打开，false 为关闭
- (void)SetBgmDeviceEnabled:(bool)enable;

/// 结束时不关闭系统声音录制
- (void)StopWithoutSystemAudio;

/// 使用 blackhole 录制系统声音
/// @param use yes 使用， no 不使用
- (void)SetUseBlackHole:(bool)use;

/// 请求屏幕录制权限
- (bool)RequestScreenCaptureAccess;

/// 录制源
/// @param sourceType 录制视频源
- (void)SetRecorderSourceType:(LVRecorderSourceType)sourceType;

/// 驱动设备名称
- (NSString *)GetAudioPluginDeviceName;

/// 设置仅仅使用摄像头采集和预览相关功能，不实用录制以及音频相关功能
- (void)SetOnlyCameraCapture:(bool)onlyCamera;

/// 获取麦克风设备音量
/// @param deviceName 设备名称
- (int)GetMicrophoneVolume:(NSString *)deviceName;

/// 设置麦克风音量
/// @param deviceName 设备名称
/// @param volume 音量 (0 -- 100)
- (void)SetMicrophoneVolume:(NSString *)deviceName volume:(int)volume;

/// 获取当前进程信息
- (NSArray <LVProcess *> *)GetCurrentRunningApplications;

@end
#endif


@interface LVRTCEngine (DEPRECATED)

/// 开始播放音乐文件及混音（声音伴奏）
/// @param filePath 文件路径
/// @param replace true: 只推动设置的本地音频文件，不传输麦克风收录的音频  false：音频文件内容将会和麦克风采集的音频流进行混音
/// @param loop 指定音频文件循环播放的次数，正整数：循环的次数 -1：无限循环
/// @return 0 ： 方法调用成功，!0：失败
-(int)startAudioMixing:(NSString *)filePath replace:(bool)replace loop:(int)loop;

/// 是否使用国际版本，该接口已废弃，SDK 内部会自动调度到国际或国内服务
/// @param env YES 为国际版本，NO 为国内版本
+ (void)setUseInternationalEnv:(bool)env;

/// 设置手动管理视频输出方向，该方法需要先调用 enableVideoAutoRotation，将自动旋转方法关闭才能生效
/// @param rotation 视频输出方向，（默认是 LVVideoRotation_0）
-(void)setOutputVideoRotation:(LVVideoRotation)rotation;

@end


NS_ASSUME_NONNULL_END
