通过阅读本文,您可以了解移动端RTS SDK与依赖FFmpeg的其他播放器(以ijk为例)集成的方法。
前提条件
背景信息
- 移动端RTS SDK与其他播放器引擎集成,需要将RTS SDK集成为插件拓展支持ARTC协议,为了降低开发难度,对于依赖FFmpeg的其他播放器引擎,可以参考移动端RTS SDK中的rtsdec.c文件,该文件将RTS SDK封装成了FFmpeg demuxer插件。移动端RTS SDK请参见SDK下载。
- 目前RTS只提供armv7a和arm64的动态库。
- 本文的操作基于ijk tag:k0.8.8。
Android平台集成
- ijkplayer集成RTS SDK作为插件。
ijkplayer集成RTS SDK作为插件有两种方法,优、缺点如下所示:
集成方法 优点 缺点 拓展ijk中FFmpeg的demuxer(简称:拓展FFmpeg) 使用更加简单,不需要根据ARTC的URL做逻辑区分。 需要重新编译FFmpeg库。 ijkplayer中添AVInputFormat(简称:拓展ijk) 不需要编译FFmpeg ff_player.c中需要添加部分逻辑代码。 - 拓展FFmpeg的方法
- 修改ijkplayer/init-android.sh中的
pull_fork
,只保留armv7a
和arm64
, 并执行该脚本。 - 修改ijkplayer/Android/contrib/compile-ffmpeg.sh中
FF_ACT_ARCHS_64
,只保留armv7a
和arm64
。 - 将RTS SDK中的rtsdec.c文件复制到ijkplayer/android/contrib/ffmpeg-arm64/libavformat和ijkplayer/android/contrib/ffmpeg-armv7a/libavformat目录下。
- 修改Makefile文件并编译rtsdec.c文件。
修改ijkplayer/android/contrib/ffmpeg-arm64/libavformat/Makefile和ijkplayer/android/contrib/ffmpeg-armv7a/libavformat/Makefile。
- 修改allformats.c,默认支持ARTC协议。
修改ijkplayer/android/contrib/ffmpeg-arm64/libavformat/allformats.c和ijkplayer/android/contrib/ffmpeg-armv7a/libavformat/allformats.c。
extern AVInputFormat ff_rtc_demuxer; av_register_input_format(&ff_rtc_demuxer);
- 修改FFmpeg编译脚本支持PCM解码(RTS SDK输出的是PCM数据)。
/config/module-lite.sh脚本中加入如下内容:
# aliyun rts export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=pcm_s16be_planar" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=pcm_s16le" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=pcm_s16le_planar"
- 编译。
添加ANDROID_NDK环境变量(r12b)。在ijkplayer/android/contrib目录下执行./compile-ffmpeg.sh all。
- 检查ijkplayer/android/contrib/build目录下是否有对应的FFmpeg编译输出文件。
- 修改ijkplayer/Android/compile-ijk.sh,
ACT_ABI_64
中只保留armv7a
和arm64
。 - 放入RTS的动态库。
将RTS对应架构的动态库放入到ijkplayer/android/contrib/build/ffmpeg-arm64/output和ijkplayer/android/contrib/build/ffmpeg-armv7a/output中,将头文件rts_api.h和rts_messages.h拷贝到ijkplayer/android/contrib/build/ffmpeg-arm64/output/include和ijkplayer/android/contrib/build/ffmpeg-armv7a/output/include中。
- 引入RTS的动态库。
修改ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ffmpeg/Android.mk和ijkplayer/android/ijkplayer/ijkplayer-arm64/src/main/jni/ffmpeg/Android.mk文件。
include $(CLEAR_VARS) LOCAL_MODULE := rtssdk LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/libRtsSDK.so include $(PREBUILT_SHARED_LIBRARY)
- ijkplayer依赖RTS动态库。
修改ijkplayer/ijkmedia/ijkplayer/Android.mk文件。
- ff_fflay.c中加入RTS逻辑。
设置给ARTC的AVInputFormat函数指针。修改ijkplayer/ijkmedia/ijkplayer/ff_ffplay.c文件。
extern AVInputFormat ff_rtc_demuxer; extern int artc_reload(AVFormatContext *ctx); extern void av_set_rts_demuxer_funcs(const struct rts_glue_funcs *funcs); extern void artc_set_rts_param(char* key, char* value); extern long long artc_get_state(AVFormatContext *ctx, int key); int version = 2; const struct rts_glue_funcs* rts_funcs = get_rts_funcs(version); // set to ffmpeg plugin av_set_rts_demuxer_funcs(rts_funcs); artc_set_rts_param((char*)"AutoReconnect", (char*)"false");
- 编译。
在ijkplayer/android目录下执行./compile-ijk.sh all。
- 修改ijkplayer/init-android.sh中的
- 拓展ijk的方法
- 修改FFmpeg编译脚本支持PCM解码(RTS SDK输出的是PCM数据),然后编译FFmpeg,不需要将RTS SDK依赖进去。
/config/module-lite.sh脚本中加入以下内容:
# aliyun rts export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=pcm_s16be_planar" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=pcm_s16le" export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=pcm_s16le_planar"
- ijkplayer依赖RTS。
将RTS SDK库文件放入工程,修改Android.mk 等操作。详情请参见拓展FFmpeg的方法相应的步骤。
- ff_fflay.c中加入RTS逻辑,区分ARTC协议头,使用指定的AVInputFormat。
if(strncmp(is->filename, "artc://", 7) == 0) { extern AVInputFormat ff_rtc_demuxer; extern int artc_reload(AVFormatContext *ctx); extern void av_set_rts_demuxer_funcs(const struct rts_glue_funcs *funcs); extern void artc_set_rts_param(char* key, char* value); extern long long artc_get_state(AVFormatContext *ctx, int key); int version = 2; const struct rts_glue_funcs* rts_funcs = get_rts_funcs(version); // set to ffmpeg plugin av_set_rts_demuxer_funcs(rts_funcs); artc_set_rts_param((char*)"AutoReconnect", (char*)"false"); is->iformat = &ff_rtc_demuxer; } else { if(ffp->iformat_name) is->iformat = av_find_input_format(ffp->iformat_name); }
- 将rtsdec.c放入到ijkplayer/ijkmedia/ijkplayer目录下,并且编写该目录下android.mk,添加该文件的编译。
LOCAL_SRC_FILES += rtsdec.c
- 修改FFmpeg编译脚本支持PCM解码(RTS SDK输出的是PCM数据),然后编译FFmpeg,不需要将RTS SDK依赖进去。
- 拓展FFmpeg的方法
- 客户工程集成ijkplayer。
- 将RtsNetSDK.jar 包导入到工程中。
- 在使用RTS播放的Activity内加入
System.loadLibrary("RtsSDK");
static { System.loadLibrary("RtsSDK"); }
导入模块:ijkplayer-arm64、ijkplayer-armv7a、ijkplayer-java。
- 调用ijkplayer接口。
- 创建ijkplayer。
mIjkPlayer = new IjkMediaPlayer();
- 设置回调。
mIjkPlayer.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() { @Override public void onPrepared(IMediaPlayer iMediaPlayer) { } }); mIjkPlayer.setOnInfoListener(new IMediaPlayer.OnInfoListener() { @Override public boolean onInfo(IMediaPlayer iMediaPlayer, int arg1, int arg2) { }); mIjkPlayer.setOnVideoSizeChangedListener(new IMediaPlayer.OnVideoSizeChangedListener() { @Override public void onVideoSizeChanged(IMediaPlayer iMediaPlayer, int width, int height, int sarNum, int sarDen) { } }); mIjkPlayer.setOnErrorListener(new IMediaPlayer.OnErrorListener() { @Override public boolean onError(IMediaPlayer iMediaPlayer, int framework_err, int impl_err) { return false; } });
- 设置显示窗口。
mIjkPlayer.setSurface(surface);
- 设置播放源。
mIjkPlayer.setDataSource("artc://xxx");
- 状态控制。
public void prepare() { if(mIjkPlayer != null){ mIjkPlayer.prepareAsync(); } } @Override public void start() { if(mIjkPlayer != null){ mIjkPlayer.start(); } } public void pause() { if(mIjkPlayer != null){ mIjkPlayer.pause(); } } public void stop() { if(mIjkPlayer != null){ mIjkPlayer.stop(); } } public void release() { if(mIjkPlayer != null){ mIjkPlayer.release(); } }
- 创建ijkplayer。
iOS平台集成
- ijkplayer集成RTS SDK作为插件。
ijkplayer集成RTS SDK作为插件有两种方法,优、缺点如下所示:
集成方法 优点 缺点 拓展ijk中FFmpeg的demuxer(简称:拓展FFmpeg) 使用更加简单,不需要根据ARTC的URL做逻辑区分。 需要重新编译FFmpeg库。 ijkplayer中添AVInputFormat(简称:拓展ijk) 不需要编译FFmpeg ff_player.c中需要添加部分逻辑代码。 - 拓展FFmpeg的方法
- 在ijkplayer目录下,执行init-ios.sh。
- 进入ijkplayer/ios目录,将rtsdec.c复制到ffmpeg-$arch/libavformat中,修改libavformat/Makefile和allformats.c。详情请参见拓展FFmpeg的方法相应的步骤。
- 编译。
在ijkplayer/ios目录下,执行./compile-ffmpeg.sh all。
- 查看ijkplayer/ios/build/universal目录下是否有输出的FFmpeg库。
- 将RtsSDK.framework放入到ijkplayer/ios/IJKMediaDemo/IJKMediaDemo目录下。
- 使用xcode打开ios/IJKMediaDemo/IJKMediaDemo.xcodeproj。
- 为IJKMediaPlayer.xcodeproj添加RtsSDK.framework的依赖。
- ff_fflay.c中加入RTS逻辑。详情请参见拓展FFmpeg的方法相应的步骤。
- 拓展ijk的方法
- 编译FFmpeg,不需要依赖RTS SDK拓展FFmpeg。
- ijkplayer依赖RTS。详情请参见拓展FFmpeg的方法相应的步骤。
- 将rtsdec.c 拖入到工程中。
- 修改ff_ffplay.c代码。详情请参见拓展FFmpeg的方法相应的步骤。
- 拓展FFmpeg的方法
- 客户工程集成播放器引擎和RTS SDK。将ijkplayer输出的引擎framework和RTS SDK的framework拖入到工程。
- 调用播放器引擎的接口。
- 创建ijkplayer。
_ijkPlayer = [[IJKFFMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:_url] withOptions:options]; _ijkPlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; _ijkPlayer.view.frame = self.basePlayerView.playerView.bounds; _ijkPlayer.scalingMode = IJKMPMovieScalingModeAspectFit; //缩放模式 _ijkPlayer.shouldAutoplay = YES; //开启自动播放
- 播放控制。
- (void)prepareToPlay; - (void)play; - (void)pause; - (void)stop;
- 创建ijkplayer。