直播云

  • 直播云 > SDK 下载 > 播放端 >QPlayer2 Windows端 > 基于 Core 的 QPlayer2 接入指南 > 基础能力使用

    基础能力使用

    最近更新时间: 2024-03-26 15:00:25

    快速开始 中,我们完成了qplayer2播放器的创建\播放\销毁,本文介绍如何使用qplayer2的播放能力

    播放

    创建播放数据

    QMedia::QMediaModelBuilder* pmodel_builder = new QMedia::QMediaModelBuilder;
    //添加播放地址
    pmodel_builder->add_stream_element(user_type, url_type, quality, url, is_selected, referer, back_up_url, render_type);
    //添加字幕地址
    pmodel_builder->add_subtitle_element(subtitle_name, subtitle_url,subtitle_is_selected);
    //创建 QMediaModel
    //is_live 是否是直播。true 直播,false 点播
    //reconstruct_time_line 是否重构时间轴,true 重构,false 不重构
    QMedia::QMediaModel* pmodel = pmodel_builder->build(is_live, reconstruct_time_line);
    

    add_stream_element 属性说明

    属性名 属性说明
    userType 用户自定义Type,目前预留,可以填空字符串
    url 资源地址
    urlType 媒体的资源属性 只包含视频/只包含音频/同时有视频音频
    quality 清晰度
    isSelected 是否起播时播放该流
    backupUrl 备用地址
    referer http/https 协议的地址 支持该属性
    renderType 视频的渲染类型
    hlsDrmKey 私有DRM解密的key,用在私有hls加密视频播放的场景中
    mp4DrmKey mp4 drm 的解密 key 用于 CENC-AES-CTR 加密的视频播放场景中
    mp4QNDrmComKey mp4 七牛私有 drm 的解密 comkey 用于七牛私有 mp4 加密的视频播放场景中
    mp4QNDrmFileKey mp4 七牛私有 drm 的解密 filekey 用于七牛私有 mp4 加密的视频播放场景中

    MP4 加密

    目前 QPlayer2 支持七牛私有加密以及显式的 CENC-AES-CTR 加密,暂不支持隐式加密。CENC-AES-CTR 的初始化向量(IV) 由加密工具随机生成并存储在加密后的 MP4 文件中,QPlayer2 读取 MP4 文件的 IV 和QMediaModel 存储的 mp4DrmKey 进行解密。

    播放 mp4 加密视频

    QMedia::QMediaModelBuilder* pmodel_builder = new QMedia::QMediaModelBuilder;
    //添加 CENC-AES-CTR 加密视频播放地址
    pmodel_builder->add_stream_element_mp4_drm(user_type, url_type, quality, url, is_selected, referer, back_up_url,mp4_drm_key, render_type);
    //添加 hls 加密视频播放地址
    pmodel_builder->add_stream_element_hls_drm(user_type, url_type, quality, url, is_selected, referer, back_up_url,hls_drm, render_type);
    //添加七牛私有 MP4 加密视频播放地址
    pmodel_builder->add_stream_element_qn_mp4_drm(user_type, url_type, quality, url, is_selected, referer, back_up_url,mp4_qn_drm_com_key,mp4_qn_drm_file_key, render_type);
    //添加字幕地址
    pmodel_builder->add_subtitle_element(subtitle_name, subtitle_url,subtitle_is_selected);
    //创建 QMediaModel
    //is_live 是否是直播。true 直播,false 点播
    //reconstruct_time_line 是否重构时间轴,true 重构,false 不重构
    QMedia::QMediaModel* pmodel = pmodel_builder->build(is_live, reconstruct_time_line);
    

    对 MP4 文件进行 CENC-AES-CTR 加密

    可以选择 ffmpeg 对一个 MP4 进行加密。加密命令如下:

    ffmpeg -i test2.mp4  -vcodec copy -acodec copy -encryption_scheme cenc-aes-ctr -encryption_key c7e16c4403654b85847037383f0c2db3 -encryption_kid a7e61c373e219033c21091fa607bf3b8 encrypted_IV_test.mp4
    

    命令说明

    test2.mp4 为输入文件

    encrypted_IV_test.mp4 为输出文件

    -vcodec copy 和 -acodec copy :指定视频流和音频流的编码方式为原始流的拷贝,即不进行重新编码,保持与原始文件相同的编码格式。

    -encryption_scheme cenc-aes-ctr :设置加密方案为 CENC-AES-CTR,即采用 CTR 模式进行加密。

    -encryption_key c7e16c4403654b85847037383f0c2db3 指定加密所使用的密钥,即解密所使用的 key。这里的c7e16c4403654b85847037383f0c2db3 是一个示例密钥,您可以替换为您自己的密钥,格式要求为:16字节的16进制数据。

    -encryption_kid a7e61c373e219033c21091fa607bf3b8:指定加密所使用的密钥标识符(KID)。这里的 a7e61c373e219033c21091fa607bf3b8 是一个示例 KID,您可以替换为您自己的密钥标识符, 格式要求为:16字节的16进制数据。

    加密后可通过ffplay 4.4 版本进行播放验证,播放正常即可。命令如下:

    ffplay encrypted_IV_test.mp4 -decryption_key c7e16c4403654b85847037383f0c2db3
    

    视频URL类型枚举

    enum class QUrlType : uint32_t {
    QAUDIO_AND_VIDEO = 0,
    //仅包含音频
    QAUDIO = 1,
    //仅包含视频
    QVIDEO = 2,
    //无
    NONE = 3
    };
    

    播放媒体资源

    /// <summary>
    /// 播放音视频资源
    /// </summary>
    /// <param name="pmedia_model"> 音视频资源 </param>
    /// <param name="start_pos"> 起播时间戳 毫秒 </param>
    /// <returns> true: 调用成功 false: 调用失败 </returns>
    mpPlayerWindow->get_control_handler()->play_media_model(pmodel, 0);
    

    播放错误监听

    添加监听前实现接口 QIPlayerMediaNetworkListener 。当视频起播时,如果遇到网络等问题原因,导致没有和服务器建立链接,那么会导致视频播放失败,总共会有3次重试机会,3次都失败的情况下会回调onOpenFailed方法。
    当视频已经起播后,在中途遇到网络等问题原因,进入buffer, 那么内核会一直重试,直到再次连接上服务端继续播放,或者用户通过接口停止播放该视频,在重试的过程中 onReconnectStart / onReconnectEnd 会被回调,那么可以监控回调的次数来做业务层的结束播放的策略,当然在正常播放的情况下,这两个方法也是会被回调的,所以最好结合buffer的回调数据一起使用。

    /// <summary>
    /// 开始重连
    /// </summary>
    /// <param name="user_type"> 重连 url 的 userType </param>
    /// <param name="url_type">重连 url 的 urlType </param>
    /// <param name="url"> 重连的 url </param>
    /// <param name="retry_time"> 重连 url 的次数 </param>
    void on_reconnect_start(const std::string & user_type, QMedia::QUrlType url_type, const std::string & url, int retry_time) override;
    
    /// <summary>
    /// 重连结束
    /// </summary>
    /// <param name="user_type"> 重连 url 的 userType </param>
    /// <param name="url_type"> 重连 url 的 urlType </param>
    /// <param name="url"> 重连的 url </param>
    /// <param name="retry_time"></param>
    /// <param name="error"> 重连 url 的次数 </param>
    void on_reconnect_end(const std::string & user_type, QMedia::QUrlType url_type, const std::string & url, int retry_time, QMedia::QOpenError error) override;
    
    /// <summary>
    /// 打开失败
    /// </summary>
    /// <param name="user_type"> 打开失败 url 的 userType </param>
    /// <param name="url_type"> 打开失败 url 的 urlType </param>
    /// <param name="url"> 打开失败的 url </param>
    /// <param name="error">  打开失败 url 的 错误码 </param>
    void on_open_failed(const std::string & user_type, QMedia::QUrlType url_type, const std::string & url, QMedia::QOpenError error) override;
    
    void on_reconnect_start(const std::string &user_type, QMedia::QUrlType url_type, const std::string& url, int retry_time){
    }
    
    void on_reconnect_end(const std::string &user_type, QMedia::QUrlType url_type, const std::string& url, int retry_time, QMedia::QOpenError error) {
    }
    
    void on_open_failed(const std::string &user_type, QMedia::QUrlType url_type, const std::string& url, QMedia::QOpenError error){
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_media_network_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_media_network_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_media_network_listeners();
    

    播放错误码枚举

    enum class QPLAYER_API QOpenError : int64_t {
    UNKNOW = 10000,
    NONE = 0, 
    IOERROR = -5,
    INTERRUPT = -1414092869,
    URL_INVALID = -875574520,
    FORMAT_INVALID = -1094995529
    };
    

    暂停播放

    /// <summary>
    /// 暂停渲染
    /// </summary>
    /// <returns> true: 调用成功 false: 调用失败 </returns>
    mpPlayerWindow->get_control_handler()->pause_render();
    

    恢复播放

    /// <summary>
    /// 在暂停渲染状态下 恢复渲染
    /// </summary>
    /// <returns> true: 调用成功 false: 调用失败 </returns>
    mpPlayerWindow->get_control_handler()->resume_render();
    

    停止当前视频播放

    /// <summary>
    /// 停止当前视频播放
    /// </summary>
    /// <returns> true: 调用成功 false: 调用失败 </returns>
    mpPlayerWindow->get_control_handler()->stop();
    

    鉴权

    鉴权功能介绍见鉴权相关文档

    强制网络鉴权

    调用该接口时,会强制进行网络鉴权

    /// <summary>
    /// 下一次鉴权强制通过网络鉴权
    /// </summary>
    /// <returns> true: 调用成功 false: 调用失败 </returns>
    mpPlayerWindow->get_control_handler()->force_authentication_from_network();
    

    鉴权监听

    添加监听前实现接口 QIPlayerAuthenticationListener 协议。

    /// <summary>
    /// 鉴权失败
    /// </summary>
    /// <param name="error"> 鉴权失败错误码 </param>
    void on_authentication_failed(QMedia::QAuthenticationErrorType error) override;
    
    /// <summary>
    /// 鉴权成功
    /// </summary>
    void on_authentication_success() override;
    
    void on_authentication_failed(QMedia::QAuthenticationErrorType error){
    }
    
    void on_authentication_success(){
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_authentication_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_authentication_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_authentication_listeners();
    

    鉴权错误码枚举

    enum class QPLAYER_API QAuthenticationErrorType : uint32_t {
    	NONE = 0,                //鉴权出错
    	NO_BASE_AUTH = 1,		 //缺少基础功能权限
    	NO_VR_AUTH = 2,			 //缺少 VR 功能权限
    	NO_BLIND_AUTH = 3,		 //缺少色盲功能权限
    	NO_SEI_AUTH = 4,		 //缺少 SEI 功能权限
    	NO_SRT_AUTH = 5			 //缺少 SRT 功能权限
    };
    

    切换视频进度

    参数为要定位的position 单位毫秒

    /// <summary>
    /// seek
    /// </summary>
    /// <param name="position"> seek 的位置 单位 ms </param>
    /// <returns></returns>
    mpPlayerWindow->get_control_handler()->seek(100);
    

    切换视频进度结果监听

    添加监听前实现接口 QIPlayerSeekListener

    /// <summary>
    /// seek 成功回调
    /// </summary>
    void on_seek_success() override;
    
    /// <summary>
    ///  seek 失败回调
    /// </summary>
    void on_seek_failed() override;
    
    void on_seek_success() {
    }
    
    void on_seek_failed() {
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_seek_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_seek_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_seek_listeners();
    

    视频解码方式

    目前支持的解码方式有:软解、硬解、自动,一般情况下,使用自动,内核会根据手机的硬件情况,要播放的视频资源编码格式等信息,挑选合适的解码方式进行解码,各个解码方式的优劣情况如下
    软解: 解码较慢,但是兼容性好,适用于所有手机
    硬解:解码性能高,但是有一定兼容性,比如某些视频资源的编码格式,硬解芯片不支持。并且相对于软解,首帧的速度慢。

    设置优先选择哪种解码方式

    设置完成后下一次播放生效.
    最终的解码方式可能不是设置的,在设置的解码方式不能正确解码时,内核会进行降级,选择其他能正确解码的方式

    /// <summary>
    /// 设置解码方式
    /// </summary>
    /// <param name="type"> 解码方式 </param>
    /// <returns> true: 调用成功 false: 调用失败 </returns>
    mpPlayerWindow->get_control_handler()->set_decode_type(QMedia::QPlayerSetting::QPlayerDecoder::QPLAYER_DECODER_SETTING_AUTO);
    

    优先选择的解码方式枚举

    该枚举主要用于设置解码方式

    enum class QPLAYER_API QPlayerDecoder : uint16_t
    {
    	//自动选择
    	QPLAYER_DECODER_SETTING_AUTO = 0,
    	//硬解优先
    	QPLAYER_DECODER_SETTING_HARDWARE_PRIORITY = 1,
    	//软解优先
    	QPLAYER_DECODER_SETTING_SOFT_PRIORITY = 2,
    };
    

    播放器视频解码监听相关

    添加监听前实现接口 QIPlayerVideoDecodeListender 协议。

    /// <summary>
    /// 播放器解码类型回调
    /// </summary>
    /// <param name="type"> 解码类型 </param>
    void on_video_decode_by_type(QMedia::QDecoderType type) override;
    
    /// <summary>
    /// 解码失败回调
    /// </summary>
    /// <param name="retry"> 是否降级重试成功 true 是 false 否 </param>
    void on_decode_failed(bool retry) override;
    
    /// <summary>
    /// 如果当前视频解码所在设备或者 sdk 不支持,则回调该函数
    /// </summary>
    /// <param name="codec_id"> 视频解码的 id  </param>
    void on_not_support_codec_format(int codec_id) override;
    
    void on_video_decode_by_type(QMedia::QDecoderType type) {
    }
    
    void on_decode_failed(bool retry) {
    }
    
    void on_not_support_codec_format(int codec_id) {
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_video_decode_type_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_video_decode_type_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_video_decode_type_listeners();
    

    解码方式枚举

    该枚举主要用于监听返回的解码方式

    enum class QPLAYER_API QDecoderType : uint32_t {
    	NONE = 0,
    	SOFTWARE = 1,
    	HARDWARE = 31
    };
    

    设置起播方式

    下一次播放生效

    /// <summary>
    /// 设置起播方式
    /// </summary>
    /// <param name="action"> 起播方式 </param>
    /// <returns> true: 调用成功 false: 调用失败 </returns>
    mpPlayerWindow->get_control_handler()->set_start_action(QMedia::QPlayerSetting::QPlayerStart::QPLAYER_START_SETTING_PLAYING);
    

    起播方式枚举

    enum class  QPlayerStart : uint16_t {
    	//起播播放
    	QPLAYER_START_SETTING_PLAYING = 0,
    	//起播暂停在首帧
    	QPLAYER_START_SETTING_PAUSE = 1,
    };
    

    设置 seek 方式

    下一次播放生效

    /// <summary>
    /// 设置seek方式
    /// </summary>
    /// <param name="mode"> seek方式 </param>
    /// <returns> true: 调用成功 false: 调用失败 </returns>
    mpPlayerWindow->get_control_handler()->set_seek_mode(QMedia::QPlayerSetting::QPlayerSeek::QPLAYER_SEEK_SETTING_NORMAL);
    

    seek方式枚举

    enum class  QPlayerSeek : uint16_t {
    	//关键帧seek,每次seek 都seek到离目标位置向前的最近的一个关键帧,耗时少
    	QPLAYER_SEEK_SETTING_NORMAL = 0,
    	//精准seek,耗时比关键帧seek多,且耗时和视频的gop间隔的大小成正比
    	QPLAYER_SEEK_SETTING_ACCURATE = 1
    };
    

    播放器状态

    在整个播放器实例生命周期中,播放会在不同的状态中切换,用户可以通过监听播放器状态,实现上层业务逻辑,
    比如在视频播放完时,展示其他视频的推荐页,那么只需监听播放器状态回调,待回调的状态是COMPLETED,则展示推荐页

    播放器状态枚举

    enum class QPLAYER_API QPlayerState : uint32_t {
    	NONE = 0,//初始状态
    	INIT = 1,//播放器开始创建各种对象 没有对应的state 创建完对象就上报这个状态
    	PREPARE = 2,//开始拉视频数据解码变换等,重新换地址后,都走这个状态
    	PLAYING = 4,//播放中
    	PAUSED_RENDER = 6,//用户暂停
    	COMPLETED = 7,//播放完成
    	SEEKING = 8, //SEEK
    	STOPPED = 9,//播放器停止中
    	MISTAKE = 10,//播放出错(是否需要分 可恢复 和 不可恢复 )
    	END = 11,//播放器释放各种对象完成
    	MEDIA_ITEM_PREPARE = 12, //开始拉视频数据解码变换等,重新换地址后,都走这个状态 针对Media Item的play 方式
    	RELEASE = 13 //播放器结束,且释放各类资源
    };
    

    播放器状态变更监听相关

    添加监听前需要签订QIPlayerStateChangeListener协议。

    /// <summary>
    /// 当前的播放状态发生改变时回调
    /// </summary>
    /// <param name="state"> 当前的播放状态 </param>
    void on_state_changed(QMedia::QPlayerState state) override;
    
    void on_state_changed(QMedia::QPlayerState state) {
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_state_change_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_state_change_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_state_change_listeners();
    

    播放速度

    播放速度的调整范围建议在0.25-2.0之间,这样会有一个比较好的效果

    设置播放速度

    参数为倍速值

    /// <summary>
    /// 设置播放速度
    /// </summary>
    /// <param name="speed"> 需要设置的倍速 </param>
    /// <returns> true: 调用成功 false: 调用失败 </returns>
    mpPlayerWindow->get_control_handler()->set_speed(0.5);
    

    速度变更监听相关

    添加监听前实现接口 QIPlayerSpeedListener

    /// <summary>
    /// 播放速度改变回调
    /// </summary>
    /// <param name="speed"> 当前的播放速度 </param>
    void on_speed_changed(float speed) override;
    
    void on_speed_changed(float speed) {
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_speed_change_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_speed_change_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_speed_change_listeners();
    

    清晰度

    QPlayer2 提供的清晰度能力是无缝切换清晰度方案,在切换过程中,画面是连续的画面,不会出现类似跳帧的情况。
    使用无缝切换清晰度功能,必须在 mediaModel 中配置多路清晰度,如果使用非 immediately 方式(即异步方式)时,同时只能有一次切换会话存在,会话结束后,才能切下一次

    切换视频清晰度

    /// <summary>
    /// 切换清晰度,针对一个视频由多路url流组成的情况下,可以按找流来进行清晰度切换,
    /// 比如一个视频由2路url组成,一路视频,一路音频,那么可以只切换音频路的url达到音频的清晰度切换,也可以
    /// 只切换视频路的url达到视频的清晰度切换。
    /// </summary>
    /// <param name="user_type"> 要切换的url流的userType </param>
    /// <param name="url_type"> 要切换的url流的urlType </param>
    /// <param name="quality_index"> 要切换到哪一路清晰度 </param>
    /// <param name="immediately"> true: 立即切换,直播情况下 
    mpPlayerWindow->get_control_handler()->switch_quality(pinner_ele->get_user_type(), pinner_ele->get_url_type(), 1080, true);
    

    播放器清晰度相关监听

    添加监听前实现接口 QIPlayerQualityListener

    /// <summary>
    /// 开始切换清晰度
    /// </summary>
    /// <param name="user_type"> 切换清晰度的 URL 的 userType </param>
    /// <param name="url_type"> 切换清晰度的 URL 的 urlType </param>
    /// <param name="old_quality"> 切换清晰度前的清晰度 </param>
    /// <param name="new_quality"> 切换清晰度后的清晰度 </param>
    void on_quality_switch_start(const std::string & user_type, QMedia::QUrlType url_type, int old_quality, int new_quality) override;
    
    /// <summary>
    /// 清晰度切换完成
    /// </summary>
    /// <param name="user_type"> 切换清晰度的 URL 的 userType </param>
    /// <param name="url_type"> 切换清晰度的 URL 的 urlType </param>
    /// <param name="old_quality"> 切换清晰度前的清晰度 </param>
    /// <param name="new_quality"> 切换清晰度后的清晰度 </param>
    void on_quality_switch_complete(const std::string & user_type, QMedia::QUrlType url_type, int old_quality, int new_quality) override;
    
    /// <summary>
    /// 清晰度切换取消
    /// </summary>
    /// <param name="user_type"> 切换清晰度的 URL 的 userType </param>
    /// <param name="url_type"> 切换清晰度的 URL 的 urlType </param>
    /// <param name="old_quality"> 切换清晰度前的清晰度 </param>
    /// <param name="new_quality"> 切换清晰度后的清晰度 </param>
    void on_quality_switch_canceled(const std::string & user_type, QMedia::QUrlType url_type, int old_quality, int new_quality) override;
    
    /// <summary>
    /// 清晰度切换失败
    /// </summary>
    /// <param name="user_type"> 切换清晰度的 URL 的 userType </param>
    /// <param name="url_type"> 切换清晰度的 URL 的 urlType </param>
    /// <param name="old_quality"> 切换清晰度前的清晰度 </param>
    /// <param name="new_quality"> 切换清晰度后的清晰度 </param>
    void on_quality_switch_failed(const std::string & user_type, QMedia::QUrlType url_type, int old_quality, int new_quality) override;
    
    /// <summary>
    /// 目前仅支持同时有一个清晰度切换事件,如果前一个切换还未完成,再次切换清晰度,则会回调该函数
    /// </summary>
    /// <param name="user_type"> 切换清晰度的 URL 的 userType </param>
    /// <param name="url_type"> 切换清晰度的 URL 的 urlType </param>
    void on_quality_switch_retry_later(const std::string & user_type, QMedia::QUrlType url_type) override;
    
    void on_quality_switch_start(const std::string & user_type, QMedia::QUrlType url_type, int old_quality, int new_quality) {
    }
    
    void on_quality_switch_complete(const std::string & user_type, QMedia::QUrlType url_type, int old_quality, int new_quality)  {
    }
    
    void on_quality_switch_canceled(const std::string & user_type, QMedia::QUrlType url_type, int old_quality, int new_quality) {
    }
    
    void on_quality_switch_failed(const std::string & user_type, QMedia::QUrlType url_type, int old_quality, int new_quality) {
    }
    
    void on_quality_switch_retry_later(const std::string & user_type, QMedia::QUrlType url_type) {
    }
    
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_quality_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_quality_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_quality_listeners();
    

    直播支持多路清晰度切换

    无缝切换清晰度方案需要配置以下三个条件

    1. 首先切换的模式要选择立即切换即:immediately=true
    2. 服务端配置PTS透传,
    3. 对应的清晰度要做主动转码设置
      如果无法满足以上3个条件,那么建议用最基础的能力来实现清晰度切换,即每个清晰度都是一个media model,切换时,调用playMediaModel来播放新的清晰度流。

    视频宽高改变监听

    在视频首帧渲染时,会调用该回调,告诉上层当前的视频宽高是多少,如果在这个这个视频播放的生命周期中,宽高改变,那么还会再次调用该回调.
    添加监听前实现接口 QIPlayerVideoFrameSizeChangeListener。

    /// <summary>
    /// 推流端视频长宽变化回调
    /// </summary>
    /// <param name="width"> 宽度 </param>
    /// <param name="height"> 高度 </param>
    void on_video_frame_size_changed(int width, int height) override;
    
    void on_video_frame_size_changed(int width, int height){
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_video_frame_size_change_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_video_frame_size_change_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_video_frame_size_change_listeners();
    

    播放进度监听

    添加监听前实现接口 QIPlayerProgressListener

    只有在点播的时候 duration 和 progress 才有意义,直播的话这两个值没有参考意义

    /// <summary>
    /// 进度变更回调
    /// </summary>
    /// <param name="progress"> 当前进度 单位:毫秒 </param>
    /// <param name="duration"> 当前视频总时长 单位: 毫秒 </param>
    void on_progress_changed(int64_t progress, int64_t duration) override;
    
    void on_progress_changed(int64_t progress, int64_t duration) {
    }
    
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_progress_change_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_progress_change_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_progress_change_listeners();
    

    实时帧率

    实时帧率监听

    添加监听前实现接口 QIPlayerFPSListener

    /// <summary>
    /// fps 改变回调
    /// </summary>
    /// <param name="fps"> fps 帧率 </param>
    void on_fps_changed(long fps) override;
    
    void on_fps_changed(long fps) {
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_fps_change_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_fps_change_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_fps_change_listeners();
    

    像素格式或者音频sample格式不支持的监听

    添加监听前实现接口 QIPlayerFormatListener

    /// <summary>
    /// 当前有 format 不支持,视频无法播放
    /// </summary>
    void on_format_not_support() override;
    
    void on_format_not_support() {
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_format_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_format_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_format_listeners();
    

    缓冲拉流监听

    添加监听前实现接口 QIPlayerDownloadListener

    /// <summary>
    /// 下载数据变化回调
    /// </summary>
    /// <param name="download_speed"> 下载速度 </param>
    /// <param name="buffer_pos"> 缓冲进度 </param>
    void on_download_changed(int64_t download_speed, int64_t buffer_pos) override;
    
    void on_download_changed(int64_t download_speed, int64_t buffer_pos){
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_download_change_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_download_change_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_download_change_listeners();
    

    播放器操作不允许执行监听

    添加监听前实现接口 QIPlayerCommandNotAllowListener 。在某些状态下,一些操作将不被执行,通过该监听回调上来通知

    /// <summary>
    /// 操作不被允许的回调
    /// </summary>
    /// <param name="command_name"> 操作名称 </param>
    /// <param name="state"> 操作被检测时播放器的状态 </param>
    void on_command_not_allow(const std::string& command_name, QMedia::QPlayerState state) override;
    
    void on_command_not_allow(const std::string& command_name, QMedia::QPlayerState state){
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_command_not_allow_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_command_not_allow_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_command_not_allow_listeners();
    

    buffering 监听

    添加监听前实现接口 QIPlayerBufferingListener

    /// <summary>
    /// buffering 开始通知
    /// </summary>
    void on_buffering_start() override;
    
    /// <summary>
    /// buffering 结束通知
    /// </summary>
    void on_buffering_end() override;
    
    void on_buffering_start(){
    }
    void on_buffering_end(){
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_buffering_change_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_buffering_change_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_buffering_change_listeners();
    

    静音播放

    控制播放器静音,且该静音非系统的声音设置,仅仅只是把播放器设置为静音

    设置静音播放

    mpPlayerWindow->get_control_handler()->set_mute(false);
    

    静音播放相关监听

    添加监听前实现接口 QIPlayerAudioListener

    /// <summary>
    /// 静音状态改变回调
    /// </summary>
    /// <param name="is_mute"> 是否静音 true 静音 false 非静音 </param>
    void on_mute_changed(bool is_mute) override;
    
    void on_mute_changed(bool is_mute){
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_audio_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_audio_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_audio_listeners();
    

    截图

    调用截图接口,就会回调截图时的video画面,并以jpeg的格式返回

    mpPlayerWindow->get_control_handler()->shoot_video();
    

    截图图片类型枚举

    enum class QPLAYER_API QShootVideoType : uint32_t {
    	NONE = 0,
    	JEPG = 1
    };
    

    截图相关监听

    添加监听前实现接口 QIPlayerShootVideoListener

    /// <summary>
    /// 截图成功回调
    /// </summary>
    /// <param name="image_data"> 图片数据 </param>
    /// <param name="size"> 图片数据的长度 </param>
    /// <param name="width"> 图片的宽度 </param>
    /// <param name="height"> 图片的高度 </param>
    /// <param name="type"> 图片类型 </param>
    void on_shoot_video_success(const std::unique_ptr<uint8_t[]>& image_data, uint64_t size, int width, int height, QMedia::QShootVideoType type) override;
    
    /// <summary>
    /// 截图失败回调
    /// </summary>
    void on_shoot_video_failed() override;
    
    void on_shoot_video_success(const std::unique_ptr<uint8_t[]>& image_data, uint64_t size, int width, int height, QMedia::QShootVideoType type){
    }
    
    void on_shoot_video_failed(){
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_shoot_video_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_shoot_video_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_shoot_video_listeners();
    

    码率

    实时码率监听

    添加监听前实现接口 QIPlayerBiteRateListener

    /// <summary>
    /// 码率变化回调
    /// </summary>
    /// <param name="bit_rate"> 码率 单位:bps </param>
    void on_bite_rate_changed(int bit_rate) override;
    
    void on_bite_rate_changed(int bit_rate) {
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_bite_rate_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_bite_rate_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_bite_rate_listeners();
    

    SEI 数据回调

    用户自定义数据可以带在H264或者H265的编码帧里,用于实现一些基于时间轴的业务场景。
    开启该功能后,如果视频资源内带有SEI数据 会通过监听接口抛给业务层。
    该功能需要单独开通,具体可以联系技术支持咨询。

    开启 SEI

    mpPlayerWindow->get_control_handler()->set_sei_enable(true);
    

    SEI 数据监听

    添加监听前实现接口 QIPlayerSEIDataListener

    /// <summary>
    /// SEI 数据回调,且回调时机为 SEI 数据所在帧的时间
    /// </summary>
    /// <param name="data"> SEI 数据 </param>
    /// <param name="size"> SEI 数据的长度 </param>
    void on_sei_data(const std::unique_ptr<uint8_t[]>& data, uint64_t size) override;
    
    void on_sei_data(const std::unique_ptr<uint8_t[]>& data, uint64_t size){
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_sei_data_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_sei_data_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_sei_data_listeners();
    

    渲染相关监听

    添加监听前实现接口 QIPlayerRenderListener

    /// <summary>
    /// 首帧耗时回调
    /// </summary>
    /// <param name="elapsed_time"> 从 play_media_model 开始到首帧渲染出来的总耗时 单位:毫秒 </param>
    void on_first_frame_rendered(int64_t elapsed_time) override;
    
    void on_first_frame_rendered(int64_t elapsed_time){
    }
    
    //添加监听
    mpPlayerWindow->get_render_handler()->add_render_listener(this);
    //移除监听
    mpPlayerWindow->get_render_handler()->remove_render_listener(this);
    //移除所有监听
    mpPlayerWindow->get_render_handler()->remove_all_render_listeners();
    

    视频数据上抛相关监听

    添加监听前实现接口 QIPlayerVideoDataListener

    /// 视频数据上抛回调
    /// </summary>
    /// <param name="width"> 视频宽度 </param>
    /// <param name="height"> 视频高度 </param>
    /// <param name="video_type"> 视频类型 </param>
    /// <param name="buffer"> 视频数据 </param>
    /// <param name="size"> 视频数据长度 </param>
    void on_video_data(int width, int height, QMedia::QVideoType video_type, const std::unique_ptr<uint8_t[]>& buffer, uint64_t size) override;
    
    
    void on_video_data(int width, int height, QMedia::QVideoType video_type, const std::unique_ptr<uint8_t[]>& buffer, uint64_t size){
    }
    
    //添加监听
    mpPlayerWindow->get_render_handler()->add_player_video_data_listener(this);
    //移除监听
    mpPlayerWindow->get_render_handler()->remove_player_video_data_listener(this);
    //移除所有监听
    mpPlayerWindow->get_render_handler()->remove_all_player_video_data_listeners();
    

    音频数据上抛相关监听

    添加监听前实现接口 QIPlayerAudioDataListener

    /// 音频数据回调
    /// </summary>
    /// <param name="sample_rate"> 采样率 </param>
    /// <param name="format"> 格式 </param>
    /// <param name="channel_num"> 通道数 </param>
    /// <param name="channel_layout"> 声道 </param>
    /// <param name="audio_data"> 音频数据 </param>
    /// <param name="size">数据大小</param>
    void on_audio_data(int sample_rate, QMedia::QSampleFormat format, int channel_num, QMedia::QChannelLayout channel_layout, const std::unique_ptr<uint8_t[]>& audio_data, uint64_t size) override;
    
    void on_audio_data(int sample_rate, QMedia::QSampleFormat format, int channel_num, QMedia::QChannelLayout channel_layout, const std::unique_ptr<uint8_t[]>& audio_data, uint64_t size){
    }
    
    //添加监听
    mpPlayerWindow->get_render_handler()->add_player_audio_data_listener(this);
    //移除监听
    mpPlayerWindow->get_render_handler()->remove_player_audio_data_listener(this);
    //移除所有监听
    mpPlayerWindow->get_render_handler()->remove_all_player_audio_data_listeners();
    

    设置视频渲染比例

    mpPlayerWindow->get_render_handler()->set_render_ratio(QMedia::QPlayerSetting::QPlayerRenderRatio::QPLAYER_RATIO_SETTING_AUTO);
    

    视频比例枚举

    enum class  QPlayerRenderRatio : uint16_t {
    	//自动
    	QPLAYER_RATIO_SETTING_AUTO = 1,
    	//拉升
    	QPLAYER_RATIO_SETTING_STRETCH = 2,
    	//铺满
    	QPLAYER_RATIO_SETTING_FULL_SCREEN = 3,
    	//16:9
    	QPLAYER_RATIO_SETTING_16_9 = 4,
    	//4:3
    	QPLAYER_RATIO_SETTING_4_3 = 5
    
    };
    

    设置色觉优化

    mpPlayerWindow->get_render_handler()->set_blind_type(QMedia::QPlayerSetting::QPlayerBlind::QPLAYER_BLIND_SETTING_NONE);
    

    色觉优化枚举

    enum class  QPlayerBlind : uint16_t {
    	//无
    	QPLAYER_BLIND_SETTING_NONE = 0,
    	//红色盲
    	QPLAYER_BLIND_SETTING_RED = 1,
    	//绿色盲
    	QPLAYER_BLIND_SETTING_GREEN = 2,
    	//蓝色盲
    	QPLAYER_BLIND_SETTING_BLUE = 3
    };
    

    字幕

    字幕数据设置

    //添加字幕地址
    pmodel_builder->add_subtitle_element(subtitle_name, subtitle_url,subtitle_is_selected);
    

    设置是否开启字幕

    mpPlayerWindow->get_control_handler()->set_subtitle_enable(false);
    

    设置字幕名称

    mpPlayerWindow->get_control_handler()->set_subtitle("English");
    

    字幕监听

    添加监听前实现接口 QIPlayerSubtitleListener

    /// <summary>
    /// 字幕文本回调
    /// </summary>
    /// <param name="text"> 当前字幕的文本 </param>
    void on_subtitle_text_changed(const std::string & text) override;
    
    /// <summary>
    /// 字幕切换回调
    /// </summary>
    /// <param name="name"> 当前的字幕名称 </param>
    void on_subtitle_name_changed(const std::string & name) override;
    
    /// <summary>
    /// 字幕开启状态改变回调
    /// </summary>
    /// <param name="enable"> 当前字幕是否开启 true 开启 false 关闭 </param>
    void on_subtitle_enable(bool enable) override;
    
    /// <summary>
    /// 字幕加载结果回调
    /// </summary>
    /// <param name="name"> 字幕名称 </param>
    /// <param name="result"> 字幕加载结果 true 成功 false 失败 </param>
    void on_subtitle_loaded(const std::string & name, bool result) override;
    
    /// <summary>
    /// 字幕解码结果回调
    /// </summary>
    /// <param name="name"> 字幕名称 </param>
    /// <param name="result"> 字幕解码结果 true 成功 false 失败 </param>
    void on_subtitle_decoded(const std::string & name, bool result) override;
    
    
    void on_subtitle_text_changed(const std::string & text) {
    }
    
    void on_subtitle_name_changed(const std::string & name) {
    }
    
    void on_subtitle_enable(bool enable) {
    }
    
    void on_subtitle_loaded(const std::string & name, bool result) {
    }
    
    void on_subtitle_decoded(const std::string & name, bool result) {
    }
    
    //添加监听
    mpPlayerWindow->get_control_handler()->add_player_subtitle_listener(this);
    //移除监听
    mpPlayerWindow->get_control_handler()->remove_player_subtitle_listener(this);
    //移除所有监听
    mpPlayerWindow->get_control_handler()->remove_all_player_subtitle_listeners();
    
    以上内容是否对您有帮助?
  • Qvm free helper
    Close