一、编写目的

为了记录编译librtmp开源库过程遇到的问题,帮助后来人提供参考,希望本文能为大家提供参考。

二、简介(官方介绍)

The Real-Time Messaging Protocol (RTMP) is used for streaming multimedia content across a TCP/IP network. This API provides most client functions and a few server functions needed to support RTMP, RTMP tunneled in HTTP (RTMPT), encrypted RTMP (RTMPE), RTMP over SSL/TLS (RTMPS) and tunneled variants of these encrypted types (RTMPTE, RTMPTS). The basic RTMP specification has been published by Adobe but this API was reverse-engineered without use of the Adobe specification. As such, it may deviate from any published specifications but it usually duplicates the actual behavior of the original Adobe clients.

三、编译步骤

1、下载源码

可以从以下两个仓库下载源码,目前使用master主分支

git clone https://github.com/shishuo365/librtmp.git
git clone https://github.com/LinChengChun/librtmp.git

2、安装Android NDK

为了开发支持android平台的库,所以需要下载google官方的NDK

https://developer.android.google.cn/ndk/downloads/index.html

3、 使用android ndk 提供脚本,允许自己定制一套工具链

cd android-ndk-r13b/build/tools/
./make-standalone-toolchain.sh --platform=android-14 --install-dir=/home/cclin/android-toolchain --force
----------------------------------------------------------------------------------------------------------------------------------------
Valid options (defaults are in brackets):--help                  Print this help.
  --verbose                Enable verbose mode.
  --dryrun                Unsupported.
  --toolchain=<name>      Specify toolchain name
  --use-llvm              No-op. Clang is always available.
  --stl=<name>            Specify C++ STL [gnustl]
  --arch=<name>            Specify target architecture    默认是 arm,可以指定其他指令架构
  --abis=<list>            No-op. Derived from --arch or --toolchain.
  --ndk-dir=<path>        Unsupported.
  --package-dir=<path>    Place package file in <path> [/tmp/ndk-cclin]    如果不指定安装目录,默认生成一个压缩包,路径在/tmp/ndk-cclin
  --install-dir=<path>    Don't create package, install files to <path> instead.    指定 工具链安装目录
  --dryrun                Unsupported.
  --platform=<name>        Specify target Android platform/API level. [android-9]    指定哪个平台/API 版本
  --force                  Remove existing install directory.    强制覆盖上一次生成的文件

4、获得工具链后,就可以编译支持android平台的librtmp库了

  • 根据上一步生成的工具链,修改 librtmp 目录下的Makefile和tools/compile-librtmp-android.sh
diff --git a/Makefile b/Makefile
index 1597948..a761d8d 100644
--- a/Makefile
+++ b/Makefile
@@ -72,7 +72,7 @@ SOINST_yes=install_so
SO_DEF=$(SODEF_$(SHARED))
SO_LIB=$(SOLIB_$(SHARED))
SO_INST=$(SOINST_$(SHARED))
-
+XLDFLAGS=-llog
DEF=-DRTMPDUMP_VERSION=\"$(VERSION)\" $(CRYPTO_DEF) $(XDEF)
OPT=-O2
CFLAGS=-Wall $(ARCH_CFLAGS) $(XCFLAGS) $(INC) $(DEF) $(OPT) $(SO_DEF)
diff --git a/tools/compile-librtmp-android.sh b/tools/compile-librtmp-android.sh
old mode 100644
new mode 100755
index 032bfab..a56faa7
--- a/tools/compile-librtmp-android.sh
+++ b/tools/compile-librtmp-android.sh
@@ -8,17 +8,19 @@ if [ -z "$RTMP_ARCH" ]; then
fi# replace this path to your android NDK standalone toolchain ptah.
-RTMP_TOOLCHAIN_PATH=/Users/shishuo/Documents/app/Android-NDK-Toolchain
+#RTMP_TOOLCHAIN_PATH=/Users/shishuo/Documents/app/Android-NDK-Toolchain
+RTMP_TOOLCHAIN_PATH=/home/cclin/android-toolchain/bin/
RTMP_BUILD_ROOT=`pwd`
RTMP_BIN_ROOT=$RTMP_BUILD_ROOT/bin
RTMP_ARCH_DIR=
cd ..compile_armv7a() {
-      export CC=$RTMP_TOOLCHAIN_PATH/arm/bin/arm-linux-androideabi-gcc
-      export LD=$RTMP_TOOLCHAIN_PATH/arm/bin/arm-linux-androideabi-ld
-      export AR=$RTMP_TOOLCHAIN_PATH/arm/bin/arm-linux-androideabi-ar
-      export ARCH_CFLAGS=-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -mthumb
+      export CC=$RTMP_TOOLCHAIN_PATH/arm-linux-androideabi-gcc
+      export LD=$RTMP_TOOLCHAIN_PATH/arm-linux-androideabi-ld
+      export AR=$RTMP_TOOLCHAIN_PATH/arm-linux-androideabi-ar
+      export ARCH_CFLAGS=-march=armv7-a
+    #-mfpu=vfpv3-d16 -mfloat-abi=softfp -mthumbmake cleanmake all
}
@@ -94,6 +96,7 @@ release_librtmp() {cp -f http.h    $RTMP_BIN_ROOT/$RTMP_ARCH_DIR/include/librtmpcp -f log.h    $RTMP_BIN_ROOT/$RTMP_ARCH_DIR/include/librtmpcp -f rtmp.h    $RTMP_BIN_ROOT/$RTMP_ARCH_DIR/include/librtmp
+    #cp -f librtmp.so.1 $RTMP_BIN_ROOT/$RTMP_ARCH_DIR/librtmp.so
}if [ "$RTMP_ARCH" = "armv7a" ]; then
@@ -137,4 +140,4 @@ elif [ "$RTMP_ARCH" = "all" ]; then
elseecho "unknown architecture $RTMP_ARCH";exit 1
-fi
\ No newline at end of file
+fi
  • 跳转到 librtmp/tools 目录运行编译脚本,即可开始编译
./compile-librtmp-android.sh armv7a    // 由于只编译armv7a架构的,因此只修改了compile-librtmp-android.sh中对应的编译器有效路径,如果需要编译其他架构需要重新生成对应工具链,重新配置对应架构下面编译器的有效路径

5、生成的文件

librtmp/tools/bin/armeabi-v7a$cp ../../../librtmp.so.1 librtmp.so
librtmp/tools/bin/armeabi-v7a$ ls -R
.:
include  lib  librtmp.so./include:
librtmp./include/librtmp:
amf.h  http.h  log.h  rtmp.h./lib:
librtmp.a

6、在AS新建一个工程用于使用librtmp库

  • 项目结构
  • Android.mk
# Android.mk for rtmpLOCAL_PATH := $(call my-dir)# rtmp library
include $(CLEAR_VARS)
LOCAL_MODULE := rtmp
LOCAL_SRC_FILES := librtmp.so
include $(PREBUILT_SHARED_LIBRARY)
#include $(PREBUILT_STATIC_LIBRARY)# Program
include $(CLEAR_VARS)
LOCAL_MODULE := nativeRtmp
LOCAL_SRC_FILES := nativeRtmp.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog -lz
LOCAL_SHARED_LIBRARIES := rtmp
include $(BUILD_SHARED_LIBRARY)
-----------------------------------------------------------------上面是引用librtmp.so动态库脚本,下面是引用librtmp.a静态库脚本------------
# Android.mk for rtmpLOCAL_PATH := $(call my-dir)# rtmp library
include $(CLEAR_VARS)
LOCAL_MODULE := rtmp
#LOCAL_SRC_FILES := librtmp.so
#include $(PREBUILT_SHARED_LIBRARY)
LOCAL_SRC_FILES := librtmp.a
include $(PREBUILT_STATIC_LIBRARY)# Program
include $(CLEAR_VARS)
LOCAL_MODULE := nativeRtmp
LOCAL_SRC_FILES := nativeRtmp.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog -lz
LOCAL_STATIC_LIBRARIES := rtmp
#LOCAL_SHARED_LIBRARIES := rtmp
include $(BUILD_SHARED_LIBRARY)
  • Application.mk
#APP_ABI := all
#APP_ABI := armeabi armeabi-v7a x86
APP_ABI :=armeabi-v7a
  • rtmpJNI.java
package org.src.rtmp_get;/**
* Created by Administrator on 2015/12/4.
*/
public class rtmpJNI {public native void rtmpDeInit();public native void rtmpInit(String rtmpUrl);static {System.loadLibrary("rtmp"); // 如果编译脚本引用librtmp.so库,需要添加该句;如果引用librtmp.a,需要注释该句;引用动态库时,native调用RTMP_Close时会出现进程崩溃;引用静态库时,运行正常,所以建议引用静态库。System.loadLibrary("nativeRtmp");}}
  • MainActivity.java
package org.src.rtmp_get;import android.app.Activity;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;public class MainActivity extends Activity {private rtmpJNI  mRtmpClient ;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mRtmpClient = new rtmpJNI();mRtmpClient.rtmpInit("rtmp://192.168.1.116");}@Overrideprotected void onDestroy() {super.onDestroy();mRtmpClient.rtmpDeInit();}
}
  • nativeRtmp.c
//
// Created by Administrator on 2015/12/4.
//
#include <jni.h>
#include <assert.h>
#include <string.h>
#include "include/librtmp/rtmp.h"
#include <sys/types.h>
#include <android/log.h>#define LOG_TAG "NativeRTMP"
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
static const char *ClassName = "org/src/rtmp_get/rtmpJNI";char* pubRtmpUrl;
RTMP *pubRtmp; //rtmpvoid 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);
}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)
{
}

四、总结

根据以上记录,librtmp库最好在linux平台编译(mingw编译不成功);编译成功后,新建一个工程测试一下librtmp库的功能,前提是具有RTMP服务器,便于通信。当然,也可以使用附件的工程来测试;本文主要是记录 librtmp编译以及在APP中的应用。后续再分析librtmp、rtmp协议相关知识点。^-^

附件rtmpDumpDemo
链接:https://pan.baidu.com/s/1nvl9inn 密码:plhb

librtmp开源库与android平台编译记录相关推荐

  1. android自动路由,GitHub - greatzi/RouterKit: 又一个路由库;Android平台对页面、服务的路由框架。自动化且易用。...

    Jet RouterKit 路由库:Android平台对页面.服务的路由框架.自动化且易用. 基于APT技术(注解-编译时生成代码,不反射,无性能损耗),通过注解方式来实现URL打开Activity功 ...

  2. SeetaFace2 Android 平台编译

    SeetaFace2 Android 平台编译 欢迎入群交流 开源地址:https://github.com/seetafaceengine/SeetaFace2 SeetaFace2 人脸识别引擎包 ...

  3. ffplay android 编译,ffmpeg android 平台编译

    ? ? ?ffmpeg 在移动平台上应用十分广泛,其在音视频编解码,封装多媒体文件格式,rtsp http rtmp协议相关的音视频推流拉流具有强大的可用性.这里将自己平时为Android平台编译ff ...

  4. Unity发布Android平台错误记录

    Unity发布Android平台错误记录 (1)Cannot parse project property android.enableR8='' of type 'class java.lang.S ...

  5. Android开源库集锦 + Android场景桌面(一) 转自way

    一.兼容类库 ActionBarSherlock : Action Bar是Android 3.0后才开始支持的,ActionBarSherlock是让Action Bar功能支持2.X后的所有平台, ...

  6. ogre android 编译,Ogre3d Android平台编译教程

    上一篇我们讲了Ogre3d 在 Window平台的编译流程方法 这一篇我们介绍 Ogre3d 编译到Android 平台的方法.可以和官方英文教程对照学习. 转载自博客 http://blog.csd ...

  7. Webrtc入门——基于阿里云ubuntu 最新webrtc Android平台编译详细说明

    折腾了好多天,终于将webrtc Android平台的demo编译出来了,发现即使完全按照webrtc官网的编译指南,还是会碰到各种问题.而网上又没有更全面的说明,最后是通过查看webrtc 批处理脚 ...

  8. 条形码、二维码扫一扫和生成二维码采用ZXing3.0开源库在android studio中实现

    在开始之前先给各位上个运行效果图 二维码QRcode全称Quick Response Code 通过在一个矩形区域内使用黑白像素来进行编码 高纠错性.高可用性.高识别性 四周面有3个大的方框和一个小的 ...

  9. 手把手教你编译RS GIS开源库(一)编译ECW3.3库

    本文为本人原创,请尊重个人劳动成果 未经本人允许,严禁转载! 0 前言 ecw格式是一种基于小波压缩的遥感影像格式,其特点就是压缩率高,不需要建立影像金字塔也能快速读取.ECW最先是由ER mappe ...

最新文章

  1. 科研经验3:公众号建立实验室共享知识体系和宣传窗口
  2. 解决pip install keras报错问题
  3. 【数据平台】Eclipse+Scala开发环境(本机和集群两个运行模式)
  4. 短视频风口创业不容易,您信吗?
  5. Vue+Leaflet实现加载OSM显示地图
  6. kotlin学习笔记——内联函数
  7. 列表-列表的排序和反转
  8. spring cloud+dotnet core搭建微服务架构:服务发现(二)
  9. Spring入门(二)之下载与安装
  10. Windows下gmssl使用记录
  11. 新一代需求管理工具Trufun Bacon X正式发布!
  12. mysql python 中文_python操作mysql中文显示乱码的解决方法
  13. 分布式定时器的实现原理
  14. python经典实例pdf-Python机器学习经典实例_PDF电子书
  15. dubbo入门之微服务客户端服务端配置
  16. 写项目文档比写代码难多了
  17. SPSS数据编码(图文+数据集)【SPSS 008期】
  18. 数据分析指标到底应该怎么解读?
  19. 重发布实验、路由策略实验
  20. descriptions描述列表换行

热门文章

  1. 2021年美容师(初级)作业考试题库及美容师(初级)操作证考试
  2. 一键切换手机WIFI代理
  3. echarts中使用散点图根据后端接口动态生成点,并根据点数据动态渲染点颜色
  4. 用JavaScript实现气球漂浮
  5. 美国邮政署网站的一个高危漏洞暴露了6000万用户的数据
  6. 媒体网关的开放式结构设计考虑
  7. 基于 RabbitMQ 的实时消息推送
  8. MySQL数据库表引擎与字符集
  9. iOS 设置录音权限
  10. vscode go 未找到任何定义 无法进行go的转到定义跳转 远程