android使用libvlc开发推流的简单demo_apk

从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 ,设备网络检查一下就好了

猜你喜欢

转载自blog.csdn.net/u012459903/article/details/88641786
今日推荐