package com.aizuda.zlm4j.core;

import com.aizuda.zlm4j.callback.*;
import com.aizuda.zlm4j.structure.*;
import com.sun.jna.Library;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;

/**
 * ZLMediaKit C Api
 *
 * @author lidaofu
 * @since 2023/11/23
 **/
public interface ZLMApi extends Library {
    /*******************************初始化与配置相关**********************************/
    /**
     * 初始化环境，调用该库前需要先调用此函数
     *
     * @param cfg 库运行相关参数
     */
    void mk_env_init(MK_CONFIG cfg);

    /**
     * 初始化环境参数
     *
     * @param thread_num    线程数
     * @param log_level     日志等级 0：TRACE 1：DEBUG 2：INFO 3：WARN 4：ERROR
     * @param log_mask      日志输入 1：LOG_CONSOLE输出到控制台  2：LOG_FILE输入到文件 4：LOG_CALLBACK输出到回调函数
     * @param log_file_path 文件日志保存路径,路径可以不存在(内部可以创建文件夹)，设置为NULL关闭日志输出至文件
     * @param log_file_days 文件日志保存天数,设置为0关闭日志文件
     * @param ini_is_path   配置文件是内容还是路径
     * @param ini           配置文件内容或路径，可以为NULL,如果该文件不存在，那么将导出默认配置至该文件
     * @param ssl_is_path   ssl证书是内容还是路径
     * @param ssl           ssl证书内容或路径，可以为NULL
     * @param ssl_pwd       证书密码，可以为NULL
     */
    void mk_env_init2(int thread_num, int log_level, int log_mask, String log_file_path, int log_file_days, int ini_is_path, Pointer ini, int ssl_is_path, String ssl, String ssl_pwd);

    /**
     * 因 C API此函数被舍弃，此方法即将停用
     *
     * @param thread_num
     * @param log_level
     * @param log_mask
     * @param log_file_path
     * @param log_file_days
     * @param ini_is_path
     * @param ini
     * @param ssl_is_path
     * @param ssl
     * @param ssl_pwd
     */
    @Deprecated
    default void mk_env_init1(int thread_num, int log_level, int log_mask, String log_file_path, int log_file_days, int ini_is_path, Pointer ini, int ssl_is_path, String ssl, String ssl_pwd) {
        mk_env_init2(thread_num, log_level, log_mask, log_file_path, log_file_days, ini_is_path, ini, ssl_is_path, ssl, ssl_pwd);
    }

    /**
     * 获取本程序可执行文件路径
     *
     * @return 文件路径，使用完后需要自己mk_free
     */
    Pointer mk_util_get_exe_path();

    /**
     * 获取本程序可执行文件相同目录下文件的绝对路径
     *
     * @param relative_path 同目录下文件的路径相对,可以为null
     * @return 文件路径，使用完后需要自己mk_free
     */

    Pointer mk_util_get_exe_dir(String relative_path);

    /**
     * 获取unix标准的系统时间戳
     *
     * @return 当前系统时间戳
     */
    long mk_util_get_current_millisecond();

    /**
     * 获取时间字符串
     *
     * @param fmt 时间格式，譬如%Y-%m-%d %H:%M:%S
     * @return 时间字符串，使用完后需要自己mk_free
     */
    Pointer mk_util_get_current_time_string(String fmt);

    /**
     * 打印二进制为字符串
     *
     * @param buf 二进制数据
     * @param len 数据长度
     * @return 可打印的调试信息，使用完后需要自己mk_free
     */
    Pointer mk_util_hex_dump(Pointer buf, int len);


    /**
     * 创建ini配置对象
     */
    MK_INI mk_ini_create();

    /**
     * 返回全局默认ini配置
     *
     * @return 全局默认ini配置，请勿用mk_ini_release释放它
     */
    MK_INI mk_ini_default();


    /**
     * 加载ini配置文件内容
     *
     * @param ini ini对象
     * @param str 配置文件内容
     */
    void mk_ini_load_string(MK_INI ini, String str);

    /**
     * 加载ini配置文件
     *
     * @param ini  ini对象
     * @param file 配置文件路径
     */
    void mk_ini_load_file(MK_INI ini, String file);


    /**
     * 销毁ini配置对象
     */
    void mk_ini_release(MK_INI ini);

    /**
     * 导出为配置文件内容
     *
     * @param ini 配置对象
     * @return 配置文件内容字符串，用完后需要自行mk_free
     */
    Pointer mk_ini_dump_string(MK_INI ini);

    /**
     * 导出配置文件到文件
     *
     * @param ini  配置对象
     * @param file 配置文件路径
     */
    void mk_ini_dump_file(MK_INI ini, String file);


    /**
     * 添加或覆盖配置项
     *
     * @param ini   配置对象
     * @param key   配置名，两段式，如：field.key
     * @param value 配置值
     */
    void mk_ini_set_option(MK_INI ini, String key, String value);

    void mk_ini_set_option_int(MK_INI ini, String key, int value);


    /**
     * 获取配置项
     *
     * @param ini 配置对象
     * @param key 配置名，两段式，如：field.key
     * @return 配置不存在返回NULL，否则返回配置值
     */
    String mk_ini_get_option(MK_INI ini, String key);

    /**
     * 删除配置项
     *
     * @param ini 配置对象
     * @param key 配置名，两段式，如：field.key
     * @return 1: 成功，0: 该配置不存在
     */
    int mk_ini_del_option(MK_INI ini, String key);


    /**
     * 释放mk api内部malloc的资源
     */
    void mk_free(Pointer pointer);


    /**
     * 设置日志文件
     *
     * @param file_max_size  单个切片文件大小(MB)
     * @param file_max_count 切片文件个数
     */
    void mk_set_log(int file_max_size, int file_max_count);

    /**
     * 设置配置项
     *
     * @param key 配置项名
     * @param val 配置项值
     * @deprecated 请使用mk_ini_set_option替代
     */
    void mk_set_option(String key, String val);

    /**
     * 获取配置项的值
     *
     * @param key 配置项名
     * @deprecated 请使用mk_ini_get_option替代
     */
    String mk_get_option(String key);

    /**
     * 创建http[s]服务器
     *
     * @param port htt监听端口，推荐80，传入0则随机分配
     * @param ssl  是否为ssl类型服务器
     * @return 0:失败,非0:端口号
     */
    short mk_http_server_start(short port, int ssl);

    /**
     * 创建rtsp[s]服务器
     *
     * @param port rtsp监听端口，推荐554，传入0则随机分配
     * @param ssl  是否为ssl类型服务器
     * @return 0:失败,非0:端口号
     */
    short mk_rtsp_server_start(short port, int ssl);

    /**
     * 创建rtmp[s]服务器
     *
     * @param port rtmp监听端口，推荐1935，传入0则随机分配
     * @param ssl  是否为ssl类型服务器
     * @return 0:失败,非0:端口号
     */
    short mk_rtmp_server_start(short port, int ssl);

    /**
     * 创建rtp服务器
     *
     * @param port rtp监听端口(包括udp/tcp)
     * @return 0:失败,非0:端口号
     */
    short mk_rtp_server_start(short port);

    /**
     * 创建rtc服务器
     *
     * @param port rtc监听端口
     * @return 0:失败,非0:端口号
     */
    short mk_rtc_server_start(short port);


    /**
     * 创建websocket[s]信令服务器
     *
     * @param port websocket监听端口
     * @param ssl  是否为ssl类型服务器
     * @return 0:失败,非0:端口号
     */
    short mk_signaling_server_start(short port,int ssl);

    /**
     * 创建ice服务器
     *
     * @param port ice监听端口
     * @return 0:失败,非0:端口号
     */
    short mk_ice_server_start(short port);


    /**
     * webrtc交换sdp，根据offer sdp生成answer sdp
     *
     * @param user_data 回调用户指针
     * @param cb        回调函数
     * @param type      webrtc插件类型，支持echo,play,push
     * @param offer     webrtc offer sdp
     * @param url       rtc url, 例如 rtc://__defaultVhost/app/stream?key1=val1&key2=val2
     */
    void mk_webrtc_get_answer_sdp(Pointer user_data, IMKWebRtcGetAnwerSdpCallBack cb, String type, String offer, String url);

    void mk_webrtc_get_answer_sdp2(Pointer user_data, IMKFreeUserDataCallBack user_data_free, IMKWebRtcGetAnwerSdpCallBack cb, String type, String offer, String url);

    /**
     * 获取webrtc proxy player 信息
     *
     * @param ctx
     * @param cb
     */
    void mk_webrtc_get_proxy_player_info(MK_PROXY_PLAYER ctx, IMKWebRtcGetProxyPlayerInfoCallBack cb);

    /**
     * WebRTC-注册到信令服务器
     *
     * @param server_host 信令服务器host
     * @param server_port 信令服务器port
     * @param room_id     房间id
     * @param ssl         是否启用ssl
     * @param cb          回调函数
     */
    void mk_webrtc_add_room_keeper(String room_id,String server_host, short server_port, int ssl,IMKWebRtcRoomKeeperInfoCallBack cb,Pointer user_data);

    void mk_webrtc_add_room_keeper2(String room_id,String server_host, short server_port, int ssl,IMKWebRtcRoomKeeperInfoCallBack cb,Pointer user_data,IMKFreeUserDataCallBack user_data_free);

    /**
     * WebRTC-从信令服务器注销
     *
     * @param room_key 房间key
     * @param cb       回调函数
     */
    void mk_webrtc_del_room_keeper(String room_key, IMKWebRtcRoomKeeperInfoCallBack cb,Pointer user_data);

    void mk_webrtc_del_room_keeper2(String room_key, IMKWebRtcRoomKeeperInfoCallBack cb,Pointer user_data,IMKFreeUserDataCallBack user_data_free);

    /**
     * WebRTC-Peer查看注册信息
     *
     * @param cb 回调函数
     */
    void mk_webrtc_list_room_keeper(IMKWebRtcRoomKeeperDataCallBack cb);

    /**
     * WebRTC-信令服务器查看注册信息
     *
     * @param cb 回调函数
     */
    void mk_webrtc_list_rooms(IMKWebRtcRoomKeeperDataCallBack cb);

    /**
     * 创建srt服务器
     *
     * @param port srt监听端口
     * @return 0:失败,非0:端口号
     */
    short mk_srt_server_start(short port);


    /**
     * 创建shell服务器
     *
     * @param port shell监听端口
     * @return 0:失败,非0:端口号
     */
    short mk_shell_server_start(short port);

    /**
     * 关闭所有服务器，请在main函数退出时调用
     */
    void mk_stop_all_server();


    /*******************************流代理相关**********************************/
    /**
     * 创建一个代理播放器
     *
     * @param vhost       虚拟主机名，一般为__defaultVhost__
     * @param app         应用名
     * @param stream      流名
     * @param hls_enabled 是否生成hls
     * @param mp4_enabled 是否生成mp4
     * @return 对象指针
     */
    MK_PROXY_PLAYER mk_proxy_player_create(String vhost, String app, String stream, int hls_enabled, int mp4_enabled);

    /**
     * 创建一个代理播放器
     *
     * @param vhost       虚拟主机名，一般为__defaultVhost__
     * @param app         应用名
     * @param stream      流名
     * @param hls_enabled 是否生成hls
     * @param mp4_enabled 是否生成mp4
     * @param retry_count 重试次数，当<0无限次重试
     * @return 对象指针
     */
    MK_PROXY_PLAYER mk_proxy_player_create3(String vhost, String app, String stream, int hls_enabled, int mp4_enabled, int retry_count);


    /**
     * 创建一个代理播放器
     *
     * @param vhost  虚拟主机名，一般为__defaultVhost__
     * @param app    应用名
     * @param stream 流名
     * @param option ProtocolOption相关配置
     * @return 对象指针
     */
    MK_PROXY_PLAYER mk_proxy_player_create2(String vhost, String app, String stream, MK_INI option);


    /**
     * 创建一个代理播放器
     *
     * @param vhost       虚拟主机名，一般为__defaultVhost__
     * @param app         应用名
     * @param stream      流名
     * @param option      ProtocolOption相关配置
     * @param retry_count 重试次数，当<0无限次重试
     * @return 对象指针
     */
    MK_PROXY_PLAYER mk_proxy_player_create4(String vhost, String app, String stream, MK_INI option, int retry_count);


    /**
     * 销毁代理播放器
     *
     * @param ctx 对象指针
     */
    void mk_proxy_player_release(MK_PROXY_PLAYER ctx);


    /**
     * 开始播放
     *
     * @param ctx 对象指针
     * @param url 播放url,支持rtsp/rtmp
     */
    void mk_proxy_player_play(MK_PROXY_PLAYER ctx, String url);


    /**
     * 设置代理播放器配置选项
     *
     * @param ctx 代理播放器指针
     * @param key 配置项键,支持 net_adapter/rtp_type/rtsp_user/rtsp_pwd/protocol_timeout_ms/media_timeout_ms/beat_interval_ms/rtsp_speed
     * @param val 配置项值,如果是整形，需要转换成统一转换成string
     */
    void mk_proxy_player_set_option(MK_PROXY_PLAYER ctx, String key, String val);


    /**
     * 监听MediaSource.close()事件
     * 在选择关闭一个关联的MediaSource时，将会最终触发到该回调
     * 你应该通过该事件调用mk_proxy_player_release函数并且释放其他资源
     *
     * @param ctx       对象指针
     * @param cb        回调指针
     * @param user_data 用户数据指针
     */
    void mk_proxy_player_set_on_close(MK_PROXY_PLAYER ctx, IMKProxyPlayerCallBack cb, Pointer user_data);

    void mk_proxy_player_set_on_close2(MK_PROXY_PLAYER ctx, IMKProxyPlayerCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);


    /**
     * 设置代理第一次播放结果回调，如果第一次播放失败，可以认作是启动失败
     *
     * @param ctx            对象指针
     * @param cb             回调指针
     * @param user_data      用户数据指针
     * @param user_data_free 用户数据释放回调
     */
    void mk_proxy_player_set_on_play_result(MK_PROXY_PLAYER ctx, IMKProxyPlayerCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 获取总的观看人数
     *
     * @param ctx 对象指针
     * @return 观看人数
     */
    int mk_proxy_player_total_reader_count(MK_PROXY_PLAYER ctx);


    /*******************************RTP相关**********************************/
    /**
     * 创建GB28181 RTP 服务器
     *
     * @param port      监听端口，0则为随机
     * @param tcp_mode  tcp模式(0: 不监听端口 1: 监听端口 2: 主动连接到服务端)
     * @param stream_id 该端口绑定的流id
     * @param app 关联的app
     * @param multiplex 是否开启rtp复用 0: 不开启 1: 开启
     * @return
     */
    MK_RTP_SERVER mk_rtp_server_create(short port, int tcp_mode, String stream_id);

    MK_RTP_SERVER mk_rtp_server_create2(short port, int tcp_mode, String vhost, String app, String stream_id);

    MK_RTP_SERVER mk_rtp_server_create3(short port, int tcp_mode, String vhost, String app, String stream_id,int multiplex);


    /**
     * TCP 主动模式时连接到服务器
     *
     * @param @param    ctx 服务器对象
     * @param dst_url   服务端地址
     * @param dst_port  服务端端口
     * @param cb        连接到服务器是否成功的回调
     * @param user_data 用户数据指针
     * @return
     */
    void mk_rtp_server_connect(MK_RTP_SERVER ctx, String dst_url, short dst_port, IMKRtpServerConnectedCallBack cb, Pointer user_data);

    void mk_rtp_server_connect2(MK_RTP_SERVER ctx, String dst_url, short dst_port, IMKRtpServerConnectedCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 销毁GB28181 RTP 服务器
     *
     * @param ctx 服务器对象
     */
    void mk_rtp_server_release(MK_RTP_SERVER ctx);

    /**
     * 获取本地监听的端口号
     *
     * @param ctx 服务器对象
     * @return 端口号
     */
    short mk_rtp_server_port(MK_RTP_SERVER ctx);

    /**
     * 更新RTP服务器过滤SSRC
     * @param ctx 服务器对象
     * @param ssrc 十进制ssrc
     *
     */
    void mk_rtp_server_update_ssrc(MK_RTP_SERVER ctx,int ssrc);


    /**
     * 监听B28181 RTP 服务器接收流超时事件
     *
     * @param ctx       服务器对象
     * @param cb        回调函数
     * @param user_data 回调函数用户数据指针
     */

    void mk_rtp_server_set_on_detach(MK_RTP_SERVER ctx, IMKRtpServerDetachCallBack cb, Pointer user_data);

    void mk_rtp_server_set_on_detach2(MK_RTP_SERVER ctx, IMKRtpServerDetachCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);



    /**
     * 获取rtp推流信息
     * @param app 应用名
     * @param stream 流id
     * @param cb rtp信息获取回调
     *
     */
    void mk_rtp_get_info(String app,String stream, IMKRtpGetInfoCallBack cb);

    /**
     * 暂停RTP超时检查
     * @param app 应用名
     * @param stream 流id
     *
     */
    void mk_rtp_pause_check(String app,String stream);

    /**
     * 恢复RTP超时检查
     * @param app 应用名
     * @param stream 流id
     *
     */
    void mk_rtp_resume_check(String app,String stream);


    /*******************************播放相关**********************************/
    /**
     * 创建一个媒体源
     *
     * @param vhost       虚拟主机名，一般为__defaultVhost__
     * @param app         应用名，推荐为live
     * @param stream      流id，例如camera
     * @param duration    时长(单位秒)，直播则为0
     * @param hls_enabled 是否生成hls
     * @param mp4_enabled 是否生成mp4
     * @return 对象指针
     */
    MK_MEDIA mk_media_create(String vhost, String app, String stream, float duration, int hls_enabled, int mp4_enabled);

    /**
     * 创建一个媒体源
     *
     * @param vhost    虚拟主机名，一般为__defaultVhost__
     * @param app      应用名，推荐为live
     * @param stream   流id，例如camera
     * @param duration 时长(单位秒)，直播则为0
     * @param option   ProtocolOption相关配置
     * @return 对象指针
     */
    MK_MEDIA mk_media_create2(String vhost, String app, String stream, float duration, MK_INI option);

    /**
     * 销毁媒体源
     *
     * @param ctx 对象指针
     */
    void mk_media_release(MK_MEDIA ctx);

    /**
     * 添加音视频track
     *
     * @param ctx   mk_media对象
     * @param track mk_track对象，音视频轨道
     */
    void mk_media_init_track(MK_MEDIA ctx, MK_TRACK track);

    /**
     * 添加视频轨道，请改用mk_media_init_track方法
     *
     * @param ctx      对象指针
     * @param codec_id 0:CodecH264/1:CodecH265
     * @param width    视频宽度; 在编码时才有效
     * @param height   视频高度; 在编码时才有效
     * @param fps      视频fps; 在编码时才有效
     * @param bit_rate 视频比特率,单位bps; 在编码时才有效
     * @param width    视频宽度
     * @param height   视频高度
     * @param fps      视频fps
     * @return 1代表成功，0失败
     */
    int mk_media_init_video(MK_MEDIA ctx, int codec_id, int width, int height, float fps, int bit_rate);

    /**
     * 添加音频轨道，请改用mk_media_init_track方法
     *
     * @param ctx         对象指针
     * @param codec_id    2:CodecAAC/3:CodecG711A/4:CodecG711U/5:OPUS
     * @param channels    通道数
     * @param sample_bit  采样位数，只支持16
     * @param sample_rate 采样率
     * @return 1代表成功，0失败
     */
    int mk_media_init_audio(MK_MEDIA ctx, int codec_id, int sample_rate, int channels, int sample_bit);

    /**
     * 初始化h264/h265/aac完毕后调用此函数，
     * 在单track(只有音频或视频)时，因为ZLMediaKit不知道后续是否还要添加track，所以会多等待3秒钟
     * 如果产生的流是单Track类型，请调用此函数以便加快流生成速度，当然不调用该函数，影响也不大(会多等待3秒)
     *
     * @param ctx 对象指针
     */
    void mk_media_init_complete(MK_MEDIA ctx);

    /**
     * 输入frame对象
     *
     * @param ctx   mk_media对象
     * @param frame 帧对象
     * @return 1代表成功，0失败
     */
    int mk_media_input_frame(MK_MEDIA ctx, MK_FRAME frame);

    /**
     * 输入单帧H264视频，帧起始字节00 00 01,00 00 00 01均可，请改用mk_media_input_frame方法
     *
     * @param ctx  对象指针
     * @param data 单帧H264数据
     * @param len  单帧H264数据字节数
     * @param dts  解码时间戳，单位毫秒
     * @param pts  播放时间戳，单位毫秒
     * @return 1代表成功，0失败
     */
    int mk_media_input_h264(MK_MEDIA ctx, Pointer data, int len, long dts, long pts);

    /**
     * 输入单帧H265视频，帧起始字节00 00 01,00 00 00 01均可，请改用mk_media_input_frame方法
     *
     * @param ctx  对象指针
     * @param data 单帧H265数据
     * @param len  单帧H265数据字节数
     * @param dts  解码时间戳，单位毫秒
     * @param pts  播放时间戳，单位毫秒
     * @return 1代表成功，0失败
     */
    int mk_media_input_h265(MK_MEDIA ctx, Pointer data, int len, long dts, long pts);

    /**
     * 输入YUV视频数据
     *
     * @param ctx      对象指针
     * @param yuv      yuv420p数据
     * @param linesize yuv420p linesize
     * @param cts      视频采集时间戳，单位毫秒
     */
    void mk_media_input_yuv(MK_MEDIA ctx, Pointer yuv[], int linesize[], long cts);

    /**
     * 输入单帧AAC音频(单独指定adts头)，请改用mk_media_input_frame方法
     *
     * @param ctx  对象指针
     * @param data 不包含adts头的单帧AAC数据，adts头7个字节
     * @param len  单帧AAC数据字节数
     * @param dts  时间戳，毫秒
     * @param adts adts头，可以为null
     * @return 1代表成功，0失败
     */
    int mk_media_input_aac(MK_MEDIA ctx, Pointer data, int len, long dts, Pointer adts);

    /**
     * 输入单帧PCM音频,启用ENABLE_FAAC编译时，该函数才有效
     *
     * @param ctx  对象指针
     * @param data 单帧PCM数据
     * @param len  单帧PCM数据字节数
     * @param pts  时间戳，毫秒
     * @return 1代表成功，0失败
     */
    int mk_media_input_pcm(MK_MEDIA ctx, Pointer data, int len, long pts);

    /**
     * 输入单帧OPUS/G711音频帧，请改用mk_media_input_frame方法
     *
     * @param ctx  对象指针
     * @param data 单帧音频数据
     * @param len  单帧音频数据字节数
     * @param dts  时间戳，毫秒
     * @return 1代表成功，0失败
     */
    int mk_media_input_audio(MK_MEDIA ctx, Pointer data, int len, long dts);


    /**
     * 监听MediaSource.close()事件
     * 在选择关闭一个关联的MediaSource时，将会最终触发到该回调
     * 你应该通过该事件调用mk_media_release函数并且释放其他资源
     *
     * @param ctx       对象指针
     * @param cb        回调指针
     * @param user_data 用户数据指针
     */
    void mk_media_set_on_close(MK_MEDIA ctx, IMKCloseEventCallBack cb, Pointer user_data);

    void mk_media_set_on_close2(MK_MEDIA ctx, IMKCloseEventCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 监听播放器seek请求事件
     *
     * @param ctx       对象指针
     * @param cb        回调指针
     * @param user_data 用户数据指针
     */
    void mk_media_set_on_seek(MK_MEDIA ctx, IMKSeekEventCallBack cb, Pointer user_data);

    void mk_media_set_on_seek2(MK_MEDIA ctx, IMKSeekEventCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 监听播放器pause请求事件
     *
     * @param ctx       对象指针
     * @param cb        回调指针
     * @param user_data 用户数据指针
     */
    void mk_media_set_on_pause(MK_MEDIA ctx, IMKPauseEventCallBack cb, Pointer user_data);

    void mk_media_set_on_pause2(MK_MEDIA ctx, IMKPauseEventCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 监听播放器speed请求事件
     *
     * @param ctx       对象指针
     * @param cb        回调指针
     * @param user_data 用户数据指针
     */
    void mk_media_set_on_speed(MK_MEDIA ctx, IMKSpeedEventCallBack cb, Pointer user_data);

    void mk_media_set_on_speed2(MK_MEDIA ctx, IMKSpeedEventCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 获取总的观看人数
     *
     * @param ctx 对象指针
     * @return 观看人数
     */
    int mk_media_total_reader_count(MK_MEDIA ctx);

    /**
     * 设置MediaSource注册或注销事件回调函数
     *
     * @param ctx       对象指针
     * @param cb        回调指针
     * @param user_data 用户数据指针
     */
    void mk_media_set_on_regist(MK_MEDIA ctx, IMKSourceRegisterEventCallBack cb, Pointer user_data);

    void mk_media_set_on_regist2(MK_MEDIA ctx, IMKSourceRegisterEventCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 开始发送一路ps-rtp流(通过ssrc区分多路)，此api线程安全
     *
     * @param ctx       对象指针
     * @param dst_url   目标ip或域名
     * @param dst_port  目标端口
     * @param ssrc      rtp的ssrc，10进制的字符串打印
     * @param con_type  0: tcp主动，1：udp主动，2：tcp被动，3：udp被动
     * @param cb        启动成功或失败回调
     * @param user_data 回调用户指针
     */
    void mk_media_start_send_rtp(MK_MEDIA ctx, String dst_url, short dst_port, String ssrc, int con_type, IMKSourceSendRtpResultCallBack cb, Pointer user_data);

    void mk_media_start_send_rtp2(MK_MEDIA ctx, String dst_url, short dst_port, String ssrc, int con_type, IMKSourceSendRtpResultCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    void mk_media_start_send_rtp3(MK_MEDIA ctx, String dst_url, short dst_port, String ssrc, int con_type, MK_INI options, IMKSourceSendRtpResultCallBack cb, Pointer user_data);

    void mk_media_start_send_rtp4(MK_MEDIA ctx, String dst_url, short dst_port, String ssrc, int con_type, MK_INI options, IMKSourceSendRtpResultCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 停止某路或全部ps-rtp发送，此api线程安全
     *
     * @param ctx  对象指针
     * @param ssrc rtp的ssrc，10进制的字符串打印，如果为null或空字符串，则停止所有rtp推流
     */
    void mk_media_stop_send_rtp(MK_MEDIA ctx, String ssrc);

    /**
     * 获取所属线程
     *
     * @param ctx 对象指针
     */
    MK_THREAD mk_media_get_owner_thread(MK_MEDIA ctx);

    /*******************************轨道相关**********************************/
    /**
     * 创建track对象引用
     *
     * @param codec_id 请参考MKCodecXXX 常量定义
     * @param args     视频或音频参数
     * @return track对象引用
     */
    MK_TRACK mk_track_create(int codec_id, CodecArgs args);

    /**
     * 减引用track对象
     *
     * @param track track对象
     */
    void mk_track_unref(MK_TRACK track);

    /**
     * 引用track对象
     *
     * @param track track对象
     * @return 新的track引用对象
     */
    MK_TRACK mk_track_ref(MK_TRACK track);


    /*
     * 获取track 编码codec类型，请参考MKCodecXXX定义
     */
    int mk_track_codec_id(MK_TRACK track);

    /**
     * 获取编码codec名称
     */
    String mk_track_codec_name(MK_TRACK track);

    /**
     * 获取比特率信息
     */
    int mk_track_bit_rate(MK_TRACK track);

    /**
     * 获取轨道是否准备好
     */
    int mk_track_ready(MK_TRACK track);

    /**
     * 获取累计帧数
     */
    long mk_track_frames(MK_TRACK track);

    /**
     * 获取时间
     */
    long mk_track_duration(MK_TRACK track);

    /**
     * track是否为视频
     */
    int mk_track_is_video(MK_TRACK track);

    /**
     * 获取视频宽度
     */
    int mk_track_video_width(MK_TRACK track);

    /**
     * 获取视频高度
     */
    int mk_track_video_height(MK_TRACK track);

    /**
     * 获取视频帧率
     */
    int mk_track_video_fps(MK_TRACK track);

    /**
     * 获取视频累计关键帧数
     */
    long mk_track_video_key_frames(MK_TRACK track);

    /**
     * 获取视频GOP关键帧间隔
     */
    int mk_track_video_gop_size(MK_TRACK track);

    /**
     * 获取视频累计关键帧间隔(毫秒)
     */
    int mk_track_video_gop_interval_ms(MK_TRACK track);

    /**
     * 获取音频采样率
     */
    int mk_track_audio_sample_rate(MK_TRACK track);

    /**
     * 获取音频通道数
     */
    int mk_track_audio_channel(MK_TRACK track);

    /**
     * 获取音频位数，一般为16bit
     */
    int mk_track_audio_sample_bit(MK_TRACK track);

    /**
     * 监听frame输出事件
     *
     * @param track     track对象
     * @param cb        frame输出回调
     * @param user_data frame输出回调用户指针参数
     */
    void mk_track_add_delegate(MK_TRACK track, IMKFrameOutCallBack cb, Pointer user_data);

    void mk_track_add_delegate2(MK_TRACK track, IMKFrameOutCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 取消frame输出事件监听
     *
     * @param track track对象
     * @param tag   mk_track_add_delegate返回值
     */
    void mk_track_del_delegate(MK_TRACK track, Pointer tag);

    /**
     * 输入frame到track，通常你不需要调用此api
     */
    void mk_track_input_frame(MK_TRACK track, MK_FRAME frame);

    /*******************************推流相关**********************************/


    /**
     * 绑定的MediaSource对象并创建rtmp[s]/rtsp[s]推流器
     * MediaSource通过mk_media_create或mk_proxy_player_create或推流生成
     * 该MediaSource对象必须已注册
     *
     * @param schema 绑定的MediaSource对象所属协议，支持rtsp/rtmp
     * @param vhost  绑定的MediaSource对象的虚拟主机，一般为__defaultVhost__
     * @param app    绑定的MediaSource对象的应用名，一般为live
     * @param stream 绑定的MediaSource对象的流id
     * @return 对象指针
     */
    MK_PUSHER mk_pusher_create(String schema, String vhost, String app, String stream);

    /**
     * 绑定的MediaSource对象并创建rtmp[s]/rtsp[s]推流器
     * MediaSource通过mk_media_create或mk_proxy_player_create或推流生成
     * 该MediaSource对象必须已注册
     *
     * @param src MediaSource对象
     * @return 对象指针
     */
    MK_PUSHER mk_pusher_create_src(MK_MEDIA_SOURCE src);

    /**
     * 释放推流器
     *
     * @param ctx 推流器指针
     */
    void mk_pusher_release(MK_PUSHER ctx);

    /**
     * 设置推流器配置选项
     *
     * @param ctx 推流器指针
     * @param key 配置项键,支持 net_adapter/rtp_type/rtsp_user/rtsp_pwd/protocol_timeout_ms/media_timeout_ms/beat_interval_ms
     * @param val 配置项值,如果是整形，需要转换成统一转换成string
     */
    void mk_pusher_set_option(MK_PUSHER ctx, String key, String val);

    /**
     * 开始推流
     *
     * @param ctx 推流器指针
     * @param url 推流地址，支持rtsp[s]/rtmp[s]
     */
    void mk_pusher_publish(MK_PUSHER ctx, String url);

    /**
     * 设置推流器推流结果回调函数
     *
     * @param ctx       推流器指针
     * @param cb        回调函数指针,不得为null
     * @param user_data 用户数据指针
     */
    void mk_pusher_set_on_result(MK_PUSHER ctx, IMKPushEventCallBack cb, Pointer user_data);

    void mk_pusher_set_on_result2(MK_PUSHER ctx, IMKPushEventCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /**
     * 设置推流被异常中断的回调
     *
     * @param ctx       推流器指针
     * @param cb        回调函数指针,不得为null
     * @param user_data 用户数据指针
     */
    void mk_pusher_set_on_shutdown(MK_PUSHER ctx, IMKPushEventCallBack cb, Pointer user_data);

    void mk_pusher_set_on_shutdown2(MK_PUSHER ctx, IMKPushEventCallBack cb, Pointer user_data, IMKFreeUserDataCallBack user_data_free);

    /*******************************播放相关**********************************/


    /**
     * 创建一个播放器,支持rtmp[s]/rtsp[s]
     *
     * @return 播放器指针
     */
    MK_PLAYER mk_player_create();

    /**
     * 销毁播放器
     *
     * @param ctx 播放器指针
     */
    void mk_player_release(MK_PLAYER ctx);

    /**
     * 设置播放器配置选项
     *
     * @param ctx 播放器指针
