Android平台RTMP|RTSP直播播放器功能进阶探讨

我们需要怎样的直播播放器?

很多开发者在跟我聊天的时候,经常问我,为什么一个RTMP或RTSP播放器,你们需要设计那么多的接口,真的有必要吗?带着这样的疑惑,我们今天聊聊Android平台RTMP、RTSP播放器常规功能,如软硬解码设置、实时音量调节、实时快照、实时录像、视频view翻转和旋转、画面填充模式设定、解码后YUV、RGB数据回调等:

延迟延迟延迟

RTMP或RTSP直播播放器,特别是在一些交互场景下,对延迟要求近乎苛刻,所以,毫秒级的延迟,是一个直播播放器聊下去的基础,200-400ms的整体时延,是大家比较期望的,是的,你没看错,RTMP的也可以做到极低延迟。

软硬解码设置

Android平台特别是超过1080p的分辨率的流数据,如果设备性能一般,软解效率不一定高,这时候建议硬解码,硬解码我们分两种,一种是设置surface模式的硬解码,这种无法快照和回调yuv、rgb数据,另一种就是常规硬解,直接出原始解码后数据的,区分两种硬解码模式,我们设计了如下的接口:

java 复制代码
/**
	 * 设置视频硬解码下Mediacodec自行绘制模式(此种模式下,硬解码兼容性和效率更好,回调YUV/RGB和快照功能将不可用)
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param isHWRenderMode: 0: not enable; 1: 用SmartPlayerSetSurface设置的surface自行绘制
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetHWRenderMode(long handle, int isHWRenderMode);

调用如下:

scss 复制代码
if (isHardwareDecoder && is_enable_hardware_render_mode) {
  libPlayer.SmartPlayerSetHWRenderMode(playerHandle, 1);
}

硬解码设置如下,分别区分264、265硬解:

ini 复制代码
if (isHardwareDecoder) {
  int isSupportHevcHwDecoder = libPlayer.SetSmartPlayerVideoHevcHWDecoder(playerHandle, 1);

  int isSupportH264HwDecoder = libPlayer
    .SetSmartPlayerVideoHWDecoder(playerHandle, 1);

  Log.i(TAG, "isSupportH264HwDecoder: " + isSupportH264HwDecoder + ", isSupportHevcHwDecoder: " + isSupportHevcHwDecoder);
}

实时音量调节

实时音量调节主要用于实时静音和实时调节播放端的音量,特别是多实例播放的时候,非常有必要:

java 复制代码
/**
	 * 设置播放音量
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param volume: 范围是[0, 100], 0是静音,100是最大音量, 默认是100
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetAudioVolume(long handle, int volume);

RTSP模式设置

针对RTSP的TCP、UDP模式设置,RTSP超时时间设置,大家可能遇到过这样的场景,有些RTSP服务或网络环境下,只支持TCP或UDP,这时候,就需要有TCP/UDP模式设置,还有自动切换TCP UDP模式选项,如果连上RTSP服务,但是收不到数据,通过RTSP timeout时间来设置重连尝试间隔:

java 复制代码
/**
	 * 设置RTSP TCP/UDP模式(默认UDP模式)
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param is_using_tcp: if with 1, it will via TCP mode, while 0 with UDP mode
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetRTSPTcpMode(long handle, int is_using_tcp);

	/**
	 * 设置RTSP超时时间, timeout单位为秒,必须大于0
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param timeout: RTSP timeout setting
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetRTSPTimeout(long handle, int timeout);

	/**
	 * 设置RTSP TCP/UDP自动切换
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * NOTE: 对于RTSP来说,有些可能支持rtp over udp方式,有些可能支持使用rtp over tcp方式.
	 * 为了方便使用,有些场景下可以开启自动尝试切换开关, 打开后如果udp无法播放,sdk会自动尝试tcp, 如果tcp方式播放不了,sdk会自动尝试udp.
	 *
	 * @param is_auto_switch_tcp_udp 如果设置1的话, sdk将在tcp和udp之间尝试切换播放,如果设置为0,则不尝试切换.
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetRTSPAutoSwitchTcpUdp(long handle, int is_auto_switch_tcp_udp);

视频翻转、view旋转

java 复制代码
/**
	 * 设置视频垂直反转
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param is_flip: 0: 不反转, 1: 反转
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetFlipVertical(long handle, int is_flip);

	/**
	 * 设置视频水平反转
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param is_flip: 0: 不反转, 1: 反转
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetFlipHorizontal(long handle, int is_flip);

	/**
	 * 设置顺时针旋转, 注意除了0度之外, 其他角度都会额外消耗性能
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param degress: 当前支持 0度,90度, 180度, 270度 旋转
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetRotation(long handle, int degress);

设置视频画面填充模式

java 复制代码
/**
	 * 设置视频画面的填充模式,如填充整个view、等比例填充view,如不设置,默认填充整个view
	 * @param handle: return value from SmartPlayerOpen()
	 * @param render_scale_mode 0: 填充整个view; 1: 等比例填充view, 默认值是0
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetRenderScaleMode(long handle, int render_scale_mode);

设置实时回调下载速度间隔

通过设置下载速度回调间隔,上层可以知道当前的网络状态,也可根据回调的下载速度,做逻辑上的调整。

java 复制代码
/**
	 * Set report download speed(设置实时回调下载速度)
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param is_report: if with 1, it will report download speed, it with 0: does not it.
	 *
	 * @param report_interval: report interval, unit is second, it must be greater than 0.
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetReportDownloadSpeed(long handle, int is_report, int report_interval );

实时快照

实时快照,对RTSP或RTMP播放器来说,非常有价值,用户感兴趣的帧数据,可以直接写png文件保存下来,后续还可以针对保存下来的png数据,做二次分析。

java 复制代码
/**
	 * Set if needs to save image during playback stream(是否启动快照功能)
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param is_save_image: if with 1, it will save current image via the interface of SmartPlayerSaveCurImage(), if with 0: does not it
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSaveImageFlag(long handle, int is_save_image);

	/**
	 * Save current image during playback stream(实时快照)
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param imageName: image name, which including fully path, "/sdcard/daniuliveimage/daniu.png", etc.
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSaveCurImage(long handle, String imageName);

调用如下:

typescript 复制代码
btnCaptureImage.setOnClickListener(new Button.OnClickListener() {
  @SuppressLint("SimpleDateFormat")
  public void onClick(View v) {

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
      .format(new Date());
    String imageFileName = "dn_" + timeStamp; // 创建以时间命名的文件名称

    String imagePath = imageSavePath + "/" + imageFileName + ".png";

    Log.i(TAG, "imagePath:" + imagePath);

    libPlayer.SmartPlayerSaveCurImage(playerHandle, imagePath);
  }
});

实时录像

实时录像的重要性不言而喻,我们好多开发者对实时录像有些误区,录像不止是写文件就完事了,还需要更精细化的粒度控制,比如单个文件大小设置、只录视频或者音频,其他音频格式转AAC后录制等。

java 复制代码
/**
	 * Create file directory(创建录像目录)
	 *
	 * @param path,  E.g: /sdcard/daniulive/rec
	 *
	 * <pre> The interface is only used for recording the stream data to local side. </pre>
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerCreateFileDirectory(String path);

	/**
	 * Set recorder directory(设置录像目录)
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param path: the directory of recorder file
	 *
	 * <pre> NOTE: make sure the path should be existed, or else the setting failed. </pre>
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetRecorderDirectory(long handle, String path);

	/**
	 * Set the size of every recorded file(设置单个录像文件大小,如超过设定大小则自动切换到下个文件录制)
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @param size: (MB), (5M~500M), if not in this range, set default size with 200MB.
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetRecorderFileMaxSize(long handle, int size);

	/*
	 * 设置录像时音频转AAC编码的开关
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * aac比较通用,sdk增加其他音频编码(比如speex, pcmu, pcma等)转aac的功能.
	 *
	 * @param is_transcode: 设置为1的话,如果音频编码不是aac,则转成aac,如果是aac,则不做转换. 设置为0的话,则不做任何转换. 默认是0.
	 *
	 * 注意: 转码会增加性能消耗
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerSetRecorderAudioTranscodeAAC(long handle, int is_transcode);
	
	
	/*
	*设置是否录视频,默认的话,如果视频源有视频就录,没有就没得录, 但有些场景下可能不想录制视频,只想录音频,所以增加个开关
	*
	*@param is_record_video: 1 表示录制视频, 0 表示不录制视频, 默认是1
	*
	* @return {0} if successful
	*/
	public native int SmartPlayerSetRecorderVideo(long handle, int is_record_video);
	
	
	/*
	*设置是否录音频,默认的话,如果视频源有音频就录,没有就没得录, 但有些场景下可能不想录制音频,只想录视频,所以增加个开关
	*
	*@param is_record_audio: 1 表示录制音频, 0 表示不录制音频, 默认是1
	*
	* @return {0} if successful
	*/
	public native int SmartPlayerSetRecorderAudio(long handle, int is_record_audio);

	/**
	 * Start recorder stream(开始录像)
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerStartRecorder(long handle);

	/**
	 * Stop recorder stream(停止录像)
	 *
	 * @param handle: return value from SmartPlayerOpen()
	 *
	 * @return {0} if successful
	 */
	public native int SmartPlayerStopRecorder(long handle);

总结

实际上,除了上述提到的功能外,RTMP或RTSP播放器,还需要支持的客制化功能有支持回调H.264/H.265/AAC数据,或回到解码后的YUV或RGB数据,设置播放缓冲、设置快速播放、设置音频输出类型等,一个通用的RTSP、RTMP播放器,延迟是基础、功能完备是加分项,性能优异稳定性好,才敢推给客户,让客户在现场放心使用,无后顾之忧。

相关推荐
音视频牛哥1 小时前
从「行走」到「思考」:机器人进化之路与感知—决策链路的工程化实践
机器学习·机器人·音视频开发
chenchao_shenzhen3 天前
RK3568嵌入式音视频硬件编解码4K 60帧 rkmpp FFmpeg7.1 音视频开发
ffmpeg·音视频·rk3588·音视频开发·嵌入式开发·瑞芯微rk3568·硬件编解码
码流怪侠5 天前
Google SoundStream音频编解码器技术解析
深度学习·音视频开发
字节跳动视频云技术团队6 天前
基于 DiT 大模型与字体级分割的视频字幕无痕擦除方案,助力短剧出海
aigc·音视频开发·视频编码
音视频牛哥7 天前
跨平台轻量级RTSP服务模块技术详解与内网低延迟直播实践
音视频开发·视频编码·直播
aqi008 天前
FFmpeg开发笔记(八十)使用百变魔音AiSound实现变声特效
android·ffmpeg·音视频·直播·流媒体
aqi009 天前
FFmpeg开发笔记(七十九)专注于视频弹幕功能的国产弹弹播放器
android·ffmpeg·音视频·直播·流媒体
音视频牛哥12 天前
SmartMediaKit 模块化音视频框架实战指南:场景链路 + 能力矩阵全解析
音视频开发·视频编码·直播
子龙_12 天前
JS解析wav音频数据并使用wasm加速
前端·javascript·音视频开发