赞
踩
实际上,我们在2015年做Android平台RTSP、RTMP播放模块的时候,第一版就支持了多实例播放,因为SDK设计比较灵活,做个简单的player实例封装即可实现多实例播放(Android Unity的就有多路demo),所以官方一直没有正式demo,本次也是有个开发者提到,希望测试下我们多路播放的效果,自己又不想做封装,索性给做个版本。
废话不多说,先上图:
我们针对的功能展示,主要是播放和录像这块,先说播放:
- /*
- * SmartPlayer.java
- * Author: https://daniusdk.com
- * Created by DaniuLive on 2015/09/26.
- */
- class ButtonPlayback1Listener implements View.OnClickListener {
- public void onClick(View v) {
- if (stream_player_1_.is_playing()) {
- Log.i(TAG, "Stop player1..");
-
- boolean iRet = stream_player_1_.StopPlayer();
-
- if (!iRet) {
- Log.e(TAG, "Call StopPlayer failed..");
- return;
- }
-
- stream_player_1_.try_release();
- btn_playback1.setText("开始播放1");
- SetViewVisibility(surface_view_1_);
- } else {
- Log.i(TAG, "Start playback stream1++");
-
- int play_buffer = 0;
- int is_using_tcp = 0;
- if(!stream_player_1_.OpenPlayerHandle(playback_url_1_, play_buffer, is_using_tcp))
- return;
-
- stream_player_1_.SetView(surface_view_1_);
-
- boolean is_mute = false;
- boolean iPlaybackRet = stream_player_1_.StartPlayer(isHardwareDecoder, is_enable_hardware_render_mode, is_mute);
- if (!iPlaybackRet) {
- Log.e(TAG, "Call StartPlayer failed..");
- return;
- }
-
- btn_playback1.setText("停止播放1");
- }
- }
- }

对应的OpenPlayerHandle()实现如下:
- /*
- * LibPlayerWrapper.java.java
- * Author: https://daniusdk.com
- */
- public boolean OpenPlayerHandle(String playback_url, int play_buffer, int is_using_tcp) {
-
- if (check_native_handle())
- return true;
-
- if(!isValidRtspOrRtmpUrl(playback_url))
- return false;
-
- long handle = lib_player_.SmartPlayerOpen(application_context());
- if (0==handle) {
- Log.e(TAG, "sdk open failed!");
- return false;
- }
-
- lib_player_.SetSmartPlayerEventCallbackV2(handle, new EventHandleV2());
-
- lib_player_.SmartPlayerSetBuffer(handle, play_buffer);
-
- // set report download speed(默认2秒一次回调 用户可自行调整report间隔)
- lib_player_.SmartPlayerSetReportDownloadSpeed(handle, 1, 4);
-
- boolean isFastStartup = true;
- lib_player_.SmartPlayerSetFastStartup(handle, isFastStartup ? 1 : 0);
-
- //设置RTSP超时时间
- int rtsp_timeout = 10;
- lib_player_.SmartPlayerSetRTSPTimeout(handle, rtsp_timeout);
-
- //设置RTSP TCP/UDP模式自动切换
- int is_auto_switch_tcp_udp = 1;
- lib_player_.SmartPlayerSetRTSPAutoSwitchTcpUdp(handle, is_auto_switch_tcp_udp);
-
- lib_player_.SmartPlayerSaveImageFlag(handle, 1);
-
- // It only used when playback RTSP stream..
- lib_player_.SmartPlayerSetRTSPTcpMode(handle, is_using_tcp);
-
- lib_player_.DisableEnhancedRTMP(handle, 0);
-
- lib_player_.SmartPlayerSetUrl(handle, playback_url);
-
- set(handle);
-
- return true;
- }

对应的开始播放、停止播放设计:
- /*
- * LibPlayerWrapper.java
- * Author: https://daniusdk.com
- */
- public boolean StartPlayer(boolean is_hardware_decoder, boolean is_enable_hardware_render_mode, boolean is_mute) {
- if (is_playing()) {
- Log.e(TAG, "already playing, native_handle:" + get());
- return false;
- }
-
- SetPlayerParam(is_hardware_decoder, is_enable_hardware_render_mode, is_mute);
-
- int ret = lib_player_.SmartPlayerStartPlay(get());
- if (ret != OK) {
- Log.e(TAG, "call StartPlay failed, native_handle:" + get() + ", ret:" + ret);
- return false;
- }
-
- write_lock_.lock();
- try {
- this.is_playing_ = true;
- } finally {
- write_lock_.unlock();
- }
-
- Log.i(TAG, "call StartPlayer OK, native_handle:" + get());
- return true;
- }
-
- public boolean StopPlayer() {
- if (!check_native_handle())
- return false;
-
- if (!is_playing()) {
- Log.w(TAG, "it's not playing, native_handle:" + get());
- return false;
- }
-
- boolean is_need_call = false;
- write_lock_.lock();
- try {
- if (this.is_playing_) {
- this.is_playing_ = false;
- is_need_call = true;
- }
- } finally {
- write_lock_.unlock();
- }
-
- if (is_need_call)
- lib_player_.SmartPlayerStopPlay(get());
-
- return true;
- }

录像设计:
- /*
- * SmartPlayer.java
- * Author: https://daniusdk.com
- */
- class ButtonRecorder1Listener implements View.OnClickListener {
- public void onClick(View v) {
- if (stream_player_1_.is_recording()) {
- Log.i(TAG, "Stop recorder1..");
-
- boolean iRet = stream_player_1_.StopRecorder();
-
- if (!iRet) {
- Log.e(TAG, "Call StopRecorder failed..");
- return;
- }
-
- stream_player_1_.try_release();
- btn_recorder1.setText("开始录像1");
- } else {
- Log.i(TAG, "Start recorder stream1++");
-
- int play_buffer = 0;
- int is_using_tcp = 0;
-
- if(!stream_player_1_.OpenPlayerHandle(playback_url_1_, play_buffer, is_using_tcp))
- return;
-
- stream_player_1_.ConfigRecorderParam(recDir, 400, 1, 1, 1);
-
- boolean iRecRet = stream_player_1_.StartRecorder();
- if (!iRecRet) {
- Log.e(TAG, "Call StartRecorder failed..");
- return;
- }
-
- btn_recorder1.setText("停止录像1");
- }
- }
- }

录像参数配置选项:
- /*
- * LibPlayerWrapper.java
- * Author: https://daniusdk.com
- */
- public boolean ConfigRecorderParam(String rec_dir, int file_max_size, int is_transcode_aac,
- int is_record_video, int is_record_audio) {
-
- if(!check_native_handle())
- return false;
-
- if (null == rec_dir || rec_dir.isEmpty())
- return false;
-
- int ret = lib_player_.SmartPlayerCreateFileDirectory(rec_dir);
- if (ret != 0) {
- Log.e(TAG, "Create record dir failed, path:" + rec_dir);
- return false;
- }
-
- if (lib_player_.SmartPlayerSetRecorderDirectory(get(), rec_dir) != 0) {
- Log.e(TAG, "Set record dir failed , path:" + rec_dir);
- return false;
- }
-
- if (lib_player_.SmartPlayerSetRecorderFileMaxSize(get(),file_max_size) != 0) {
- Log.e(TAG, "SmartPlayerSetRecorderFileMaxSize failed.");
- return false;
- }
-
- lib_player_.SmartPlayerSetRecorderAudioTranscodeAAC(get(), is_transcode_aac);
-
- // 更细粒度控制录像的, 一般情况无需调用
- lib_player_.SmartPlayerSetRecorderVideo(get(), is_record_video);
- lib_player_.SmartPlayerSetRecorderAudio(get(), is_record_audio);
- return true;
- }

开始录像、结束录像:
- /*
- * LibPlayerWrapper.java
- * Author: https://daniusdk.com
- */
- public boolean StartRecorder() {
-
- if (is_recording()) {
- Log.e(TAG, "already recording, native_handle:" + get());
- return false;
- }
-
- int ret = lib_player_.SmartPlayerStartRecorder(get());
- if (ret != OK) {
- Log.e(TAG, "call SmartPlayerStartRecorder failed, native_handle:" + get() + ", ret:" + ret);
- return false;
- }
-
- write_lock_.lock();
- try {
- this.is_recording_ = true;
- } finally {
- write_lock_.unlock();
- }
-
- Log.i(TAG, "call SmartPlayerStartRecorder OK, native_handle:" + get());
- return true;
- }
-
- public boolean StopRecorder() {
- if (!check_native_handle())
- return false;
-
- if (!is_recording()) {
- Log.w(TAG, "it's not recording, native_handle:" + get());
- return false;
- }
-
- boolean is_need_call = false;
- write_lock_.lock();
- try {
- if (this.is_recording_) {
- this.is_recording_ = false;
- is_need_call = true;
- }
- } finally {
- write_lock_.unlock();
- }
-
- if (is_need_call)
- lib_player_.SmartPlayerStopRecorder(get());
-
- return true;
- }

说了这么多,以RTSP播放为例,大概说下实现的功能:
上面只是简单的播放、录像的演示,除此之外,大牛直播SDK的RTSP、RTMP播放器海康实现播放缓冲设置、软硬解码设置、实时快照、实时音量调节、实时解码后数据回调等。毫秒级延迟,完全满足对延迟、稳定性要求苛刻的场景下。感兴趣的开发者,可以单独和我沟通。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。