Android(安卓)Rtmp客户端搭建
@Author:明明不说话
@Statement:博客内容纯属个人观点,欢迎转载,转载请注明,谢谢
RTMP介绍
RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写。该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMPT/RTMPS/RTMPE等多种变种。RTMP是一种设计用来进行实时数据通信的网络协议,主要用来在Flash/AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信。支持该协议的软件包括Adobe Media Server/Ultrant Media Server/red5等。
Android的RTMP方案
Android上常用的RTMP工程可以用juv-rtmp-client,这是一款收费的软件,但是可以在网上找破解版作为学习了解使用,可以参考该示例。使用起来就是调用API,底层基本上都不要处理接触,比较方便。
同时还有一个开源工程rmtpdump,完全开源C语言代码,我们可以自己根据需要编译和定制,例如要修改rtmp协议时(rtmp内容修改添加部分字段),则rtmpdump则体现出它的优势了。
RtmpDump使用
下载RtmpDump
可以在RtmpDump网站上下载源码编译(编译方法可以网上搜索),或者使用官网已经编译好的rtmpdump-2.3-android.zip库
rtmp native实现
native代码添加
图1
按照Android jni代码方式实现添加,不清楚百度或者参考demo,可以看到代码结构里面包含了librtmp.a和librtmp.so两个文件,其实只是链接方式的不同而已,最后JNI结构如图1所示,Android.mk根据librtmp目标文件是否静态而选在PREBUILT_SHARED_LIBRARY还是PREBUILT_STATIC_LIBRARY
Android.mk按如下编写
# Android.mk for rtmpLOCAL_PATH := $(call my-dir)# rtmp libraryinclude $(CLEAR_VARS)LOCAL_MODULE := rtmpLOCAL_SRC_FILES := librtmp.soinclude $(PREBUILT_SHARED_LIBRARY) #动态库#include $(PREBUILT_STATIC_LIBRARY)# Programinclude $(CLEAR_VARS)LOCAL_MODULE := nativeRtmpLOCAL_SRC_FILES := nativeRtmp.cLOCAL_C_INCLUDES += $(LOCAL_PATH)/includeLOCAL_LDLIBS := -llog -lzLOCAL_SHARED_LIBRARIES := rtmpinclude $(BUILD_SHARED_LIBRARY)
Application.mk编写
#APP_ABI := all#APP_ABI := armeabi armeabi-v7a x86APP_ABI :=armeabi
rtmpdump jni使用
编写nativeRtmp.c,分别编写初始化,销毁和发送函数,来测试使用librtmp.so
发送函数
void send_pkt(char* buf, int buflen, int type, unsigned int timestamp){ int ret; RTMPPacket rtmp_pakt; RTMPPacket_Reset(&rtmp_pakt); RTMPPacket_Alloc(&rtmp_pakt, buflen); rtmp_pakt.m_packetType = type; rtmp_pakt.m_nBodySize = buflen; rtmp_pakt.m_nTimeStamp = timestamp; rtmp_pakt.m_nChannel = 4; rtmp_pakt.m_headerType = RTMP_PACKET_SIZE_LARGE; rtmp_pakt.m_nInfoField2 = pubRtmp->m_stream_id; memcpy(rtmp_pakt.m_body, buf, buflen); ret = RTMP_SendPacket(pubRtmp, &rtmp_pakt, 0); RTMPPacket_Free(&rtmp_pakt);}
初始化
void my_Native_rtmpInit(JNIEnv *env, jobject jobj,jstring jRtmpUrl){ const char* rtmpUrl = (*env)->GetStringUTFChars(env, jRtmpUrl, 0); pubRtmpUrl = malloc(strlen(rtmpUrl) + 1); memset(pubRtmpUrl, 0, strlen(rtmpUrl) + 1); strcpy(pubRtmpUrl, rtmpUrl); pubRtmp = RTMP_Alloc(); RTMP_Init(pubRtmp); LOGI("RTMP_Init %s", pubRtmpUrl); if (!RTMP_SetupURL(pubRtmp, pubRtmpUrl)) { LOGE("RTMP_SetupURL error"); return; } if (!RTMP_Connect(pubRtmp, NULL) ) { LOGE("RTMP_Connect error"); return; } /* if (!RTMP_ConnectStream(pubRtmp, 0)) { LOGE("RTMP_ConnectStream error"); return; }*/ LOGI("RTMP Connect ok"); send_pkt("aa", 20, RTMP_PACKET_TYPE_AUDIO, 20);}
销毁
void my_Native_rtmpDeInit(JNIEnv *env, jobject jobj){ if (RTMP_IsConnected(pubRtmp)) { RTMP_Close(pubRtmp); } RTMP_Free(pubRtmp); free(pubRtmpUrl);}
jni动态加载
这里采用JNI_OnLoad函数来加载jni的方法,供给API调用
static JNINativeMethod METHODS[]={ {"rtmpInit","(Ljava/lang/String;)V",(void *)my_Native_rtmpInit}, {"rtmpDeInit","()V",(void *)my_Native_rtmpDeInit},};JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { int retVal = -1; JNIEnv *env; if ( (*vm)->GetEnv(vm,(void **) &env, JNI_VERSION_1_4) == JNI_OK ) { jclass clazz = (*env)->FindClass(env,ClassName); if (clazz != NULL) { if ((*env)->RegisterNatives(env,clazz, METHODS,sizeof(METHODS) / sizeof(METHODS[0])) >= 0) { retVal = JNI_VERSION_1_4; }else{ LOGI("RegisterNatives Subprocess.create method failed!"); } (*env)->DeleteLocalRef(env,clazz); }else{ LOGI("className not found!"); } } return retVal;}JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved){}
ps:这里需要定义ClassName变量,例如demo中
static const char *ClassName = "org/src/rtmp_get/rtmpJNI";
就是说,是org.src.rtmp_get.rtmpJNI类调用了该jni的接口,根据实际调用类的位置和名字来修改该ClassName的名字
rtmp 应用调用
java 类实现
添加需要的libray以及申明Native本地方法,这里需要和JNINativeMethod 中定义的一致,否则会报找不到该接口。
public class rtmpJNI { public native void rtmpDeInit(); public native void rtmpInit(String rtmpUrl); static { System.loadLibrary("rtmp"); System.loadLibrary("nativeRtmp"); }}
应用实现
public class MainActivity extends Activity { private rtmpJNI mRtmpClient ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRtmpClient = new rtmpJNI(); //初始化打开链接rtmp流媒体服务器 mRtmpClient.rtmpInit("rtmp://live.hkstv.hk.lxdns.com/live/hks"); //亲测该rtmp地址可用,可以采用rtmp流播放器播放视频 } @Override protected void onDestroy() { super.onDestroy(); mRtmpClient.rtmpDeInit();//销毁断开链接 }}
ps一定要记得申明权限,否则会不能正常访问网络
android:name="android.permission.INTERNET"></uses-permission>
测试链接
可以用简易RED5流媒体服务器测试参考Windows环境搭建Red5流媒体服务器指南,执行red5.bat,然后执行上述应用,看是否能够链接上服务器。
总结
上面就是对rtmpDump的使用,可以参考如上操作,附上demo以及相关链接,Q&A。
Demo下载地址
red5流媒体服务器搭建下载地址
更多相关文章
- 基于feng streaming server 搭建Android直播测试平台
- 使用gdb在Android(安卓)Emulator中进行调试
- android串口通信以及串口协议解析
- Android使用意图链接活动和意图筛选器
- Android(安卓)开发环境下载地址 -- 百度网盘 adt-bundle android
- android关于socket编程,以聊天为例http://hi.baidu.com/yaoyuanh
- Android(安卓)Activity URL Scheme的介绍与应用
- FFmpeg 中的 log 输出到 Android(安卓)的 logcat 中
- android基于xmpp的即时通讯应用