大牛直播sdk简单播放端demo使用
来源:互联网 发布:单片机lcd1602插上重启 编辑:程序博客网 时间:2024/05/21 06:58
集成
导入依赖jar
官方例子中的SmartPlayerJni
集成注意:该java必须处在com.daniulive.smartplayer包名下,否则init会出错。
public class SmartPlayerJni { /** * Initialize Player. * * @param ctx: get by this.getApplicationContext() * * <pre>This function must be called firstly.</pre> * * @return player handle if successful, if return 0, which means init failed. */ public native long SmartPlayerInit(Object ctx); /** * Set callback event * * @param callback function * * @return {0} if successful */ public native int SetSmartPlayerEventCallback(long handle, SmartEventCallback callback); /** * Set Video HW decoder, if support HW decoder, it will return 0 * * @param isHWDecoder: 0: software decoder; 1: hardware decoder. * * @return {0} if successful */ public native int SetSmartPlayerVideoHWDecoder(long handle, int isHWDecoder); /** * Set Surface view. * * @param handle: return value from SmartPlayerInit() * * @param glSurface: surface view * * <pre> NOTE: if not set or set surface with null, it will playback audio only. </pre> * * @return {0} if successful */ public native int SmartPlayerSetSurface(long handle, Object surface); /** * Set External Render. * * @param handle: return value from SmartPlayerInit() * * @param external_render: External Render * * @return {0} if successful */ public native int SmartPlayerSetExternalRender(long handle, Object external_render); /** * Set AudioOutput Type * * @param handle: return value from SmartPlayerInit() * * @param use_audiotrack: * * <pre> NOTE: if use_audiotrack with 0: it will use auto-select output devices; if with 1: will use audiotrack mode. </pre> * * @return {0} if successful */ public native int SmartPlayerSetAudioOutputType(long handle, int use_audiotrack); /** * Set buffer * * @param handle: return value from SmartPlayerInit() * * @param buffer: * * <pre> NOTE: Unit is millisecond, range is 200-5000 ms </pre> * * @return {0} if successful */ public native int SmartPlayerSetBuffer(long handle, int buffer); /** * Set mute or not * * @param is_mute: if with 1:mute, if with 0: does not mute * * @return {0} if successful */ public native int SmartPlayerSetMute(long handle, int is_mute); /** * It's only used when playback RTSP stream * * Default with UDP mode * * @param isUsingTCP: 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); /** * Set playback orientation. * * @param handle: return value from SmartPlayerInit() * * @param surOrg: current orientation, PORTRAIT 1, LANDSCAPE with 2 * * @return {0} if successful */ public native int SmartPlayerSetOrientation(long handle, int surOrg); /** * Start playback stream * * @param handle: return value from SmartPlayerInit() * * @param uri: playback uri * * @return {0} if successful */ public native int SmartPlayerStartPlayback(long handle, String uri); /** * Close player instance. * * @param handle: return value from SmartPlayerInit() * * <pre> NOTE: it could not use player handle after call this function. </pre> * * @return {0} if successful */ public native int SmartPlayerClose(long handle);}
接收推流
public class SmartPlayer extends Activity { private SurfaceView sSurfaceView = null; private long playerHandle = 0;private static final int PORTRAIT = 1;//竖屏private static final int LANDSCAPE = 2;//横屏private static final String TAG = "SmartPlayer";private SmartPlayerJni libPlayer = null;private int currentOrigentation = PORTRAIT;private boolean isPlaybackViewStarted = false;private String playbackUrl = null;private boolean isMute = false;private boolean isHardwareDecoder = false;Button btnPopInputText;Button btnPopInputUrl;Button btnMute; Button btnStartStopPlayback;Button btnHardwareDecoder; TextView txtCopyright; TextView txtQQQun; LinearLayout lLayout = null; FrameLayout fFrameLayout = null; private Context myContext; static { System.loadLibrary("SmartPlayer");} @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); Log.i(TAG, "Run into OnCreate++"); libPlayer = new SmartPlayerJni(); myContext = this.getApplicationContext(); boolean bViewCreated = CreateView(); if(bViewCreated){ inflateLayout(LinearLayout.VERTICAL); } } /* For smartplayer demo app, the url is based on: baseURL + inputID * For example: * baseURL: rtmp://daniulive.com:1935/hls/stream * inputID: 123456 * playbackUrl: rtmp://daniulive.com:1935/hls/stream123456 * */ private void GenerateURL(String id){ if(id == null) return; if(id.equals("hks")) { playbackUrl = "rtmp://live.hkstv.hk.lxdns.com/live/hks"; return; } btnStartStopPlayback.setEnabled(true); String baseURL = "rtmp://daniulive.com:1935/hls/stream"; playbackUrl = baseURL + id; } private void SaveInputUrl(String url) { playbackUrl = ""; if ( url == null ) return; // rtmp:/ if ( url.length() < 8 ) { Log.e(TAG, "Input full url error:" + url); return; } if ( !url.startsWith("rtmp://") && !url.startsWith("rtsp://")) { Log.e(TAG, "Input full url error:" + url); return; } btnStartStopPlayback.setEnabled(true); playbackUrl = url; Log.i(TAG, "Input full url:" + url); } /* Popup InputID dialog */ private void PopDialog(){ final EditText inputID = new EditText(this); inputID.setFocusable(true); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("如 rtmp://daniulive.com:1935/hls/stream123456,\n请输入123456").setView(inputID).setNegativeButton( "取消", null); builder.setPositiveButton("确认", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { String strID = inputID.getText().toString(); GenerateURL(strID); } }); builder.show(); } private void PopFullUrlDialog(){ final EditText inputUrlTxt = new EditText(this); inputUrlTxt.setFocusable(true); inputUrlTxt.setText("rtmp://daniulive.com:1935/hls/stream"); AlertDialog.Builder builderUrl = new AlertDialog.Builder(this); builderUrl.setTitle("如 rtmp://daniulive.com:1935/hls/stream123456").setView(inputUrlTxt).setNegativeButton( "取消", null); builderUrl.setPositiveButton("确认", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { String fullUrl = inputUrlTxt.getText().toString(); SaveInputUrl(fullUrl); } }); builderUrl.show(); } /* Generate basic layout */ private void inflateLayout(int orientation) { if (null == lLayout) lLayout = new LinearLayout(this); addContentView(lLayout, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); lLayout.setOrientation(orientation); fFrameLayout = new FrameLayout(this); LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT, 1.0f); fFrameLayout.setLayoutParams(lp); Log.i(TAG, "++inflateLayout.."); sSurfaceView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); fFrameLayout.addView(sSurfaceView, 0); RelativeLayout outLinearLayout = new RelativeLayout(this); outLinearLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT)); LinearLayout lLinearLayout = new LinearLayout(this); lLinearLayout.setOrientation(LinearLayout.VERTICAL); lLinearLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); LinearLayout copyRightLinearLayout = new LinearLayout(this); copyRightLinearLayout.setOrientation(LinearLayout.VERTICAL); RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); rl.topMargin = getWindowManager().getDefaultDisplay().getHeight()-270; copyRightLinearLayout.setLayoutParams(rl); txtCopyright=new TextView(this); txtCopyright.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); txtCopyright.setText("Copyright 2014~2016 www.daniulive.com v1.0.16.0326"); copyRightLinearLayout.addView(txtCopyright, 0); txtQQQun=new TextView(this); txtQQQun.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); txtQQQun.setText("QQ群:294891451, 499687479"); copyRightLinearLayout.addView(txtQQQun, 1); /* PopInput button */ btnPopInputText = new Button(this); btnPopInputText.setText("输入urlID"); btnPopInputText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); lLinearLayout.addView(btnPopInputText, 0); btnPopInputUrl = new Button(this); btnPopInputUrl.setText("输入完整url"); btnPopInputUrl.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); lLinearLayout.addView(btnPopInputUrl, 1); /*mute button */ isMute = false; btnMute = new Button(this); btnMute.setText("静音 "); btnMute.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); lLinearLayout.addView(btnMute, 2); /*hardware decoder button */ isHardwareDecoder = false; btnHardwareDecoder = new Button(this); btnHardwareDecoder.setText("当前软解码"); btnHardwareDecoder.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); lLinearLayout.addView(btnHardwareDecoder, 3); /* Start playback stream button */ btnStartStopPlayback = new Button(this); btnStartStopPlayback.setText("开始播放 "); btnStartStopPlayback.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); lLinearLayout.addView(btnStartStopPlayback, 4); outLinearLayout.addView(lLinearLayout, 0); outLinearLayout.addView(copyRightLinearLayout, 1); fFrameLayout.addView(outLinearLayout, 1); lLayout.addView(fFrameLayout, 0); if(isPlaybackViewStarted) { btnPopInputText.setEnabled(false); btnPopInputUrl.setEnabled(false); btnHardwareDecoder.setEnabled(false); btnStartStopPlayback.setText("停止播放 "); } else { btnPopInputText.setEnabled(true); btnPopInputUrl.setEnabled(true); btnHardwareDecoder.setEnabled(true); btnStartStopPlayback.setText("开始播放 "); } /* PopInput button listener */ btnPopInputText.setOnClickListener(new Button.OnClickListener() { // @Override public void onClick(View v) { Log.i(TAG, "Run into input playback ID++"); PopDialog(); Log.i(TAG, "Run out from input playback ID--"); } }); btnPopInputUrl.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { PopFullUrlDialog(); } }); btnMute.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { isMute = !isMute; if ( isMute ) { btnMute.setText("取消静音"); } else { btnMute.setText("静音"); } if ( playerHandle != 0 ) { libPlayer.SmartPlayerSetMute(playerHandle, isMute?1:0); } } }); btnHardwareDecoder.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { isHardwareDecoder = !isHardwareDecoder; if ( isHardwareDecoder ) { btnHardwareDecoder.setText("当前硬解码"); } else { btnHardwareDecoder.setText("当前软解码"); } } }); btnStartStopPlayback.setOnClickListener(new Button.OnClickListener() { // @Override public void onClick(View v) { if(isPlaybackViewStarted) { Log.i(TAG, "Stop playback stream++"); btnStartStopPlayback.setText("开始播放 "); btnPopInputText.setEnabled(true); btnPopInputUrl.setEnabled(true); btnHardwareDecoder.setEnabled(true); libPlayer.SmartPlayerClose(playerHandle); playerHandle = 0; isPlaybackViewStarted = false; Log.i(TAG, "Stop playback stream--"); } else { Log.i(TAG, "Start playback stream++"); playerHandle = libPlayer.SmartPlayerInit(myContext); if(playerHandle == 0) { Log.e(TAG, "surfaceHandle with nil.."); return; } libPlayer.SetSmartPlayerEventCallback(playerHandle, new EventHande()); libPlayer.SmartPlayerSetSurface(playerHandle, sSurfaceView); //if set the second param with null, it means it will playback audio only.. // libPlayer.SmartPlayerSetSurface(playerHandle, null); // External Render test //libPlayer.SmartPlayerSetExternalRender(playerHandle, new RGBAExternalRender()); //libPlayer.SmartPlayerSetExternalRender(playerHandle, new I420ExternalRender()); libPlayer.SmartPlayerSetAudioOutputType(playerHandle, 0); libPlayer.SmartPlayerSetBuffer(playerHandle, 200); if ( isMute ) { libPlayer.SmartPlayerSetMute(playerHandle, isMute?1:0); } if( isHardwareDecoder ) { Log.i(TAG, "check isHardwareDecoder: " + isHardwareDecoder); int hwChecking = libPlayer.SetSmartPlayerVideoHWDecoder(playerHandle, isHardwareDecoder?1:0); Log.i(TAG, "[daniulive] hwChecking: " + hwChecking); } //It only used when playback RTSP stream.. // libPlayer.SmartPlayerSetRTSPTcpMode(playerHandle, 1); //playbackUrl = "rtmp://live.hkstv.hk.lxdns.com/live/hks"; //playbackUrl = "rtsp://rtsp-v3-spbtv.msk.spbtv.com/spbtv_v3_1/214_110.sdp"; //playbackUrl = "rtmp://10.2.68.91:1935/hls/stream8"; if(playbackUrl == null){ Log.e(TAG, "playback URL with NULL..."); return; } int iPlaybackRet = libPlayer.SmartPlayerStartPlayback(playerHandle, playbackUrl); if(iPlaybackRet != 0) { Log.e(TAG, "StartPlayback strem failed.."); return; } btnStartStopPlayback.setText("停止播放 "); btnPopInputText.setEnabled(false); btnPopInputUrl.setEnabled(false); btnHardwareDecoder.setEnabled(false); isPlaybackViewStarted = true; Log.i(TAG, "Start playback stream--"); } } });} public static final String bytesToHexString(byte[] buffer) { StringBuffer sb = new StringBuffer(buffer.length); String temp; for (int i = 0; i < buffer.length; ++i) { temp = Integer.toHexString(0xff&buffer[i]); if (temp.length() < 2) sb.append(0); sb.append(temp); } return sb.toString(); } class RGBAExternalRender implements NTExternalRender { //public static final int NT_FRAME_FORMAT_RGBA = 1; //public static final int NT_FRAME_FORMAT_ABGR = 2; //public static final int NT_FRAME_FORMAT_I420 = 3; private int width_ = 0; private int height_ = 0; private int row_bytes_ = 0; private ByteBuffer rgba_buffer_ = null; @Override public int getNTFrameFormat() { Log.i(TAG, "RGBAExternalRender::getNTFrameFormat return "+ NT_FRAME_FORMAT_RGBA); return NT_FRAME_FORMAT_RGBA; } @Override public void onNTFrameSizeChanged(int width, int height) { width_ = width; height_ = height; row_bytes_ = width_ * 4; Log.i(TAG, "RGBAExternalRender::onNTFrameSizeChanged width_:" + width_ + " height_:" + height_); rgba_buffer_ = ByteBuffer.allocateDirect(row_bytes_*height_); } @Override public ByteBuffer getNTPlaneByteBuffer(int index) { if ( index == 0 ) { return rgba_buffer_; } else { Log.e(TAG, "RGBAExternalRender::getNTPlaneByteBuffer index error:" + index); return null; } } @Override public int getNTPlanePerRowBytes(int index) { if ( index == 0 ) { return row_bytes_; } else { Log.e(TAG, "RGBAExternalRender::getNTPlanePerRowBytes index error:" + index); return 0; } } public void onNTRenderFrame() { if( rgba_buffer_ == null ) return; rgba_buffer_.rewind(); // copy buffer // test // byte[] test_buffer = new byte[16]; // rgba_buffer_.get(test_buffer); //Log.i(TAG, "RGBAExternalRender:onNTRenderFrame rgba:" + bytesToHexString(test_buffer)); } } class I420ExternalRender implements NTExternalRender { //public static final int NT_FRAME_FORMAT_RGBA = 1; //public static final int NT_FRAME_FORMAT_ABGR = 2; //public static final int NT_FRAME_FORMAT_I420 = 3; private int width_ = 0; private int height_ = 0; private int y_row_bytes_ = 0; private int u_row_bytes_ = 0; private int v_row_bytes_ = 0; private ByteBuffer y_buffer_ = null; private ByteBuffer u_buffer_ = null; private ByteBuffer v_buffer_ = null; @Override public int getNTFrameFormat() { Log.i(TAG, "I420ExternalRender::getNTFrameFormat return "+ NT_FRAME_FORMAT_I420); return NT_FRAME_FORMAT_I420; } @Override public void onNTFrameSizeChanged(int width, int height) { width_ = width; height_ = height; y_row_bytes_ = (width_ + 15) & (~15); u_row_bytes_ = ((width_+1)/2 + 15) & (~15); v_row_bytes_ = ((width_+1)/2 + 15) & (~15); y_buffer_ = ByteBuffer.allocateDirect(y_row_bytes_*height_); u_buffer_ = ByteBuffer.allocateDirect(u_row_bytes_*(height_+1)/2); v_buffer_ = ByteBuffer.allocateDirect(v_row_bytes_*(height_+1)/2); Log.i(TAG, "I420ExternalRender::onNTFrameSizeChanged width_=" + width_ + " height_=" + height_ + " y_row_bytes_=" + y_row_bytes_ + " u_row_bytes_=" + u_row_bytes_ + " v_row_bytes_=" + v_row_bytes_); } @Override public ByteBuffer getNTPlaneByteBuffer(int index) { if ( index == 0 ) { return y_buffer_; } else if ( index == 1 ) { return u_buffer_; } else if ( index == 2 ) { return v_buffer_; } else { Log.e(TAG, "I420ExternalRender::getNTPlaneByteBuffer index error:" + index); return null; } } @Override public int getNTPlanePerRowBytes(int index) { if ( index == 0 ) { return y_row_bytes_; } else if ( index == 1) { return u_row_bytes_; } else if (index == 2 ) { return v_row_bytes_; } else { Log.e(TAG, "I420ExternalRender::getNTPlanePerRowBytes index error:" + index); return 0; } } public void onNTRenderFrame() { if ( y_buffer_ == null ) return; if ( u_buffer_ == null ) return; if ( v_buffer_ == null ) return; y_buffer_.rewind(); u_buffer_.rewind(); v_buffer_.rewind(); // copy buffer // test // byte[] test_buffer = new byte[16]; // y_buffer_.get(test_buffer); // Log.i(TAG, "I420ExternalRender::onNTRenderFrame y data:" + bytesToHexString(test_buffer)); // u_buffer_.get(test_buffer); // Log.i(TAG, "I420ExternalRender::onNTRenderFrame u data:" + bytesToHexString(test_buffer)); // v_buffer_.get(test_buffer); // Log.i(TAG, "I420ExternalRender::onNTRenderFrame v data:" + bytesToHexString(test_buffer)); } } class EventHande implements SmartEventCallback { @Override public void onCallback(int code, long param1, long param2, String param3, String param4, Object param5){ switch (code) { case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STARTED: Log.i(TAG, "开始。。"); break; case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTING: Log.i(TAG, "连接中。。"); break; case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTION_FAILED: Log.i(TAG, "连接失败。。"); break; case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_CONNECTED: Log.i(TAG, "连接成功。。"); break; case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_DISCONNECTED: Log.i(TAG, "连接断开。。"); break; case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_STOP: Log.i(TAG, "关闭。。"); break; case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_RESOLUTION_INFO: Log.i(TAG, "分辨率信息: width: " + param1 + ", height: " + param2); break; case EVENTID.EVENT_DANIULIVE_ERC_PLAYER_NO_MEDIADATA_RECEIVED: Log.i(TAG, "收不到媒体数据,可能是url错误。。"); } } } /* Create rendering */ private boolean CreateView() { if(sSurfaceView == null) { /* * useOpenGLES2: * If with true: Check if system supports openGLES, if supported, it will choose openGLES. * If with false: it will set with default surfaceView; */ sSurfaceView = NTRenderer.CreateRenderer(this, true); } if(sSurfaceView == null) { Log.i(TAG, "Create render failed.."); return false; } return true;} @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Log.i(TAG, "Run into onConfigurationChanged++"); if (null != fFrameLayout) { fFrameLayout.removeAllViews(); fFrameLayout = null; } if (null != lLayout) { lLayout.removeAllViews(); lLayout = null; } if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Log.i(TAG, "onConfigurationChanged, with LANDSCAPE。。"); inflateLayout(LinearLayout.HORIZONTAL); currentOrigentation = LANDSCAPE; } else { Log.i(TAG, "onConfigurationChanged, with PORTRAIT。。"); inflateLayout(LinearLayout.VERTICAL); currentOrigentation = PORTRAIT; } if(!isPlaybackViewStarted) return; libPlayer.SmartPlayerSetOrientation(playerHandle, currentOrigentation); Log.i(TAG, "Run out of onConfigurationChanged--"); } @Override protected void onDestroy(){Log.i(TAG, "Run into activity destory++"); if(playerHandle!=0){libPlayer.SmartPlayerClose(playerHandle);playerHandle = 0;}super.onDestroy(); finish(); }}
使用
结合publisher推送端使用,播放端输入id开始播放即可实现直播功能。
jni初始化的时候会检测app_name
未授权版本,限制app-name,如果需要集成到自己工程里面调试,可以用以下名字:
android推送端:SmartPublisherSDKDemo
android后台Service推送:SmartServicePublisherSDKDemo
android播放器:SmartPlayerSDKDemo
iOS推送端:SmartiOSPublisher
iOS播放器:SmartiOSPlayer
(目前个人免费,商用收费)
0 0
- 大牛直播sdk简单播放端demo使用
- 大牛直播推送-直播SDK
- 一张图了解大牛直播SDK
- ios 视频播放/直播demo
- 阿里云直播服务 sdk demo php
- 使用vitamio做直播demo
- 使用七牛直播平台SDK和环信IM低仿映客直播APP的应用
- 直播APP的应用(使用七牛直播平台SDK和环信IM低仿映客)
- Ucloud直播云SDK的简单集成
- android视频播放简单demo
- 七牛直播demo链接
- 七牛直播服务sdk
- LZH_IJKPlayer-一个最简单使用的视频播放器,集成于bilibili开源直播播放器(ijkplayer)
- Android 直播播放器+弹幕使用总结
- Android直播播放器+弹幕使用总结
- ijkplayer的使用解析-视频播放,直播
- 使用EasyDrawin进行简单直播
- 微信sdk超级简单demo
- 在Linux系统中使用Fish Shell的入门指引
- React Native--Image控件
- 对称素数
- modbus通讯协议及其原理
- bufferedinputstream 不阻塞原理
- 大牛直播sdk简单播放端demo使用
- eclipse svn
- rabbitMQ-server控制台安装报错启动失败,黑窗口一闪即过Applying plugin configuration to rabbit .. failed.
- c# Windows 服务程序编写与调试
- 安装jupyter,添加新核及遇到的问题
- 网络综合布线工程技术实训室解决方案(转载)
- Android应用架构
- Swift学习笔记
- C#Timer控件的使用