从linux版本的libvlc推流demo,https://blog.csdn.net/u012459903/article/details/88600045 移到android app上使用,调通,迫不及待上一篇博文,虽然还没来得及整理好各种细节。
如图,测试android机和 pc连接到同一局域网,启动app,用pc上的vlc播放器 播放网络串流:输入app中设置的流地址
环境:已经编译好的 vlc-android 源码, (之前的博文已经编译过,过程较复杂),用android studio 编译好的的vlc_android 工程,最终得到的是一个 vlc播放器,和一个vlc-android/libvlc/build/outputs/aar/libvlc-armv8-3.1.5.aar(编译vlc_android 的时候可以选择架构,这里我选的 arm64,即 在vlc-android目录下执行# ./compile.sh -a arm64 得到的包), 这个libvlc-armv8-3.1.5.aar即 vlc官方封装的 提供给android使用的api包。
apk java层即调用其中的api包来实现视频解码达到播放视频的目的。但是我们现在要用的vlc的推流功能(上一篇博文在linux上的demo),官方是没有进行jni的封装的。分析如下:
vlc 编译后得到的一个libvlc.so , java层要调用到这个库里面的函数,没办法,得通过jni层调用,所以vlc播放器对于自己要用到的libvlc.so中的函数,都在jni层作了一层包装:
现在我推流要用到的libvlc的函数
vlc = libvlc_new(0, NULL);
libvlc_vlm_add_broadcast(vlc, media_name, url, sout, 0, NULL, true, false);
libvlc_vlm_play_media(vlc, media_name);
在官方的jni层找一下,并没有 libvlc_vlm_add_broadcast这个函数的包装,自己来写一个这个函数的jni层转换。
......
#include<android/log.h>
#define MY_LOG_TAG "from-jni-vlc-send" // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,MY_LOG_TAG,__VA_ARGS__) // 定义LOGD类型
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,MY_LOG_TAG,__VA_ARGS__) // 定义LOGI类型
//下面的jni的头文件自行生成
JNIEXPORT jboolean JNICALL Java_com_example_wangxiancan_rtsp_1vlc_CallNative_1vlc_1send_SendStream
(JNIEnv *env, jobject classx, jboolean bLoop, jstring filePath)
{
LOGI("logi hello world \n");
#if 1
libvlc_instance_t *vlc; const char *url;
//Send and playing at same time
const char *sout = "#rtp{sdp=rtsp://192.168.43.14:10086/stream}";//根据实际情况改成设备的ip地址
const char *media_name = "Lei's test";
url = "/storage/emulated/0/bydtest.mp4";
vlc = libvlc_new(0, NULL);
if(vlc == NULL)
{
LOGI("vlc == NULL %d %s \n",__LINE__,__FUNCTION__);
}
LOGI("vlc new ok! %d %s \n",__LINE__,__FUNCTION__);
libvlc_vlm_add_broadcast(vlc, media_name, url, sout, 0, NULL, true, false);
libvlc_vlm_play_media(vlc, media_name);
//play 30s usleep(30000);
while(1)
{
usleep(100*10000*10);
}
libvlc_vlm_stop_media(vlc, media_name); libvlc_vlm_release(vlc);
#endif
return 0;
}
编译得到自己的jni.so,生成这个需要native层的库函数,即 libvlc.so 和 libc++_shared.so .将vlc-android 编译得到的aar压缩包,改名为.zip,解压开找到如下的jni 层的库文件,或者直接从 vlc-android 下面的 libvlc/jni/libs/arm64-v8a 文件夹取出我们的需要的文件,这里要用到的文件只需要 libvlc.so libc++_shared.so,libvlcjni.so是官方播放器的jni层,现在用自己的jni.so
现在自己的apk有:
helloworld 工程。自行添加的 jni 层(其中的 vlc_inclue 是编译jni要用到的vlc的头文件,拷貝自 vlc/include,vlc_lib是编译jni库需要连接的libvlc.so和libc++_shared.so)
app层在helloworld 里面间接接调用到上面的函数Java_com_example_wangxiancan_rtsp_1vlc_CallNative_1vlc_1send_SendStream,成功。
问题:1.0 app要sd卡读写权限和网络权限,android 6.0 之后获取sd卡读写权限是要动态获取的,这个百度一下即可
2.0 上述都完成,运行app ,log中报错 libvlc: VLM not compiled-in!
vlm模块没有编译进去,跟着这个信息在vlc源码中查找可以发现,我们编译的vlc-ubuntu 版本中的 config.h是开启了ENABLE_VLM的, 而vlc-android源码中的vlc-android/vlc/build-android-aarch64-linux-android/config.h 中的vlm是被关闭了。通过查找和跟踪 compile.sh,找到了开启vlm的办法。
1.0删除 vlc-android top 目录下的文件 compile-libvlc.sh中的 disable-vlm
2.0 rm –r libvlc/jni/libs/arm64-v8a 目录 (即编译生成的目录)
3.0 rm –r vlc/build-android-aarch64-linux-android/config.h (这个config.h是脚本里面自动生成的修改了compile-libvlc.h的配置,2 3 步骤都是为了确保新的配置会被使用,分析compile.sh就可以知道 少了这个目录脚本才会去重新配置,重新编译)
3.0 解决上面的问题,再跑app,如果还遇到 socket bind error ,设备网络检查一下就好了