@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流媒体服务器搭建下载地址

更多相关文章

  1. 基于feng streaming server 搭建Android直播测试平台
  2. 使用gdb在Android(安卓)Emulator中进行调试
  3. android串口通信以及串口协议解析
  4. Android使用意图链接活动和意图筛选器
  5. Android(安卓)开发环境下载地址 -- 百度网盘 adt-bundle android
  6. android关于socket编程,以聊天为例http://hi.baidu.com/yaoyuanh
  7. Android(安卓)Activity URL Scheme的介绍与应用
  8. FFmpeg 中的 log 输出到 Android(安卓)的 logcat 中
  9. android基于xmpp的即时通讯应用

随机推荐

  1. 基于数据智能的区域教育大平台建设与应用
  2. 知识主题间先序关系挖掘
  3. 深度学习模型训练全流程!
  4. Linux安装
  5. 没搞明白哪里错了 我的天
  6. 我的XGBoost学习经历及动手实践
  7. Linux相关网络基础详解——OSI&TCP/IP&数
  8. 如何优雅地展示机器学习项目!
  9. 数据分析之Pandas合并操作总结
  10. 在期数较短的微观面板数据中使用双重差分