通过阅读本文,您可以了解RTS SDK与依赖FFmpeg的其他播放器(以ijk为例)集成的方法。

前提条件

您已阅读并完成ijk的编译,详情请参见ijkPlayer Github

背景信息

  • 移动端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平台集成

  1. ijkplayer集成RTS SDK作为插件。

    ijkplayer集成RTS SDK作为插件有两种方法,优、缺点如下所示:

    集成方法 优点 缺点
    拓展ijk中FFmpeg的demuxer(简称:拓展FFmpeg) 使用更加简单,不需要根据ARTC的URL做逻辑区分。 需要重新编译FFmpeg库。
    ijkplayer中添AVInputFormat(简称:拓展ijk) 不需要编译FFmpeg ff_player.c中需要添加部分逻辑代码。
    • 拓展FFmpeg的方法
      1. 修改ijkplayer/init-android.sh中的pull_fork,只保留armv7aarm64, 并执行该脚本。013
      2. 修改ijkplayer/Android/contrib/compile-ffmpeg.shFF_ACT_ARCHS_64,只保留armv7aarm64014
      3. 将RTS SDK中的rtsdec.c文件复制到ijkplayer/android/contrib/ffmpeg-arm64/libavformatijkplayer/android/contrib/ffmpeg-armv7a/libavformat目录下。
      4. 修改Makefile文件并编译rtsdec.c文件。

        修改ijkplayer/android/contrib/ffmpeg-arm64/libavformat/Makefileijkplayer/android/contrib/ffmpeg-armv7a/libavformat/Makefile

        914
      5. 修改allformats.c,默认支持ARTC协议。

        修改ijkplayer/android/contrib/ffmpeg-arm64/libavformat/allformats.cijkplayer/android/contrib/ffmpeg-armv7a/libavformat/allformats.c

        016
            extern AVInputFormat ff_rtc_demuxer;
            av_register_input_format(&ff_rtc_demuxer);
      6. 修改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"
      7. 编译。

        添加ANDROID_NDK环境变量(r12b)。在ijkplayer/android/contrib目录下执行./compile-ffmpeg.sh all

      8. 检查ijkplayer/android/contrib/build目录下是否有对应的FFmpeg编译输出文件。
      9. 修改ijkplayer/Android/compile-ijk.shACT_ABI_64中只保留armv7aarm64017
      10. 放入RTS的动态库。

        将RTS对应架构的动态库放入到ijkplayer/android/contrib/build/ffmpeg-arm64/outputijkplayer/android/contrib/build/ffmpeg-armv7a/output中,将头文件rts_api.h和rts_messages.h拷贝到ijkplayer/android/contrib/build/ffmpeg-arm64/output/includeijkplayer/android/contrib/build/ffmpeg-armv7a/output/include中。

      11. 引入RTS的动态库。
        修改ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ffmpeg/Android.mkijkplayer/android/ijkplayer/ijkplayer-arm64/src/main/jni/ffmpeg/Android.mk文件。018
        include $(CLEAR_VARS)
        LOCAL_MODULE := rtssdk
        LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/libRtsSDK.so
        include $(PREBUILT_SHARED_LIBRARY)
      12. ijkplayer依赖RTS动态库。
        修改ijkplayer/ijkmedia/ijkplayer/Android.mk文件。019
      13. ff_fflay.c中加入RTS逻辑。

        设置给ARTC的AVInputFormat函数指针。修改ijkplayer/ijkmedia/ijkplayer/ff_ffplay.c文件。

        021
            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");
      14. 编译。

        ijkplayer/android目录下执行./compile-ijk.sh all

    • 拓展ijk的方法
      1. 修改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"
      2. ijkplayer依赖RTS。

        将RTS SDK库文件放入工程,修改Android.mk 等操作。详情请参见拓展FFmpeg的方法相应的步骤

      3. ff_fflay.c中加入RTS逻辑,区分ARTC协议头,使用指定的AVInputFormat。053
        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);
            }
      4. 将rtsdec.c放入到ijkplayer/ijkmedia/ijkplayer目录下,并且编写该目录下android.mk,添加该文件的编译。
        LOCAL_SRC_FILES += rtsdec.c
  2. 客户工程集成ijkplayer。
    1. 将RtsNetSDK.jar 包导入到工程中。
    2. 在使用RTS播放的Activity内加入System.loadLibrary("RtsSDK");
      static {
          System.loadLibrary("RtsSDK");
      }
      导入模块:ijkplayer-arm64、ijkplayer-armv7a、ijkplayer-java。060
  3. 调用ijkplayer接口。
    1. 创建ijkplayer。
      mIjkPlayer = new IjkMediaPlayer();
    2. 设置回调。
      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;
          }
      });
    3. 设置显示窗口。
      mIjkPlayer.setSurface(surface);
    4. 设置播放源。
      mIjkPlayer.setDataSource("artc://xxx");
    5. 状态控制。
      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();
          }
      }

iOS平台集成

  1. ijkplayer集成RTS SDK作为插件。

    ijkplayer集成RTS SDK作为插件有两种方法,优、缺点如下所示:

    集成方法 优点 缺点
    拓展ijk中FFmpeg的demuxer(简称:拓展FFmpeg) 使用更加简单,不需要根据ARTC的URL做逻辑区分。 需要重新编译FFmpeg库。
    ijkplayer中添AVInputFormat(简称:拓展ijk) 不需要编译FFmpeg ff_player.c中需要添加部分逻辑代码。
    • 拓展FFmpeg的方法
      1. 在ijkplayer目录下,执行init-ios.sh
      2. 进入ijkplayer/ios目录,将rtsdec.c复制到ffmpeg-$arch/libavformat中,修改libavformat/Makefile和allformats.c。详情请参见拓展FFmpeg的方法相应的步骤
      3. 编译。

        ijkplayer/ios目录下,执行./compile-ffmpeg.sh all

      4. 查看ijkplayer/ios/build/universal目录下是否有输出的FFmpeg库。
      5. 将RtsSDK.framework放入到ijkplayer/ios/IJKMediaDemo/IJKMediaDemo目录下。
      6. 使用xcode打开ios/IJKMediaDemo/IJKMediaDemo.xcodeproj
      7. 为IJKMediaPlayer.xcodeproj添加RtsSDK.framework的依赖。264
      8. ff_fflay.c中加入RTS逻辑。详情请参见拓展FFmpeg的方法相应的步骤
    • 拓展ijk的方法
      1. 编译FFmpeg,不需要依赖RTS SDK拓展FFmpeg。
      2. ijkplayer依赖RTS。详情请参见拓展FFmpeg的方法相应的步骤
      3. 将rtsdec.c 拖入到工程中。270
      4. 修改ff_ffplay.c代码。详情请参见拓展FFmpeg的方法相应的步骤
  2. 客户工程集成播放器引擎和RTS SDK。
    将ijkplayer输出的引擎framework和RTS SDK的framework拖入到工程。273
  3. 调用播放器引擎的接口。
    1. 创建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; //开启自动播放
    2. 播放控制。
      - (void)prepareToPlay;
      - (void)play;
      - (void)pause;
      - (void)stop;

Windows平台集成

  1. 下载并解压Windows端RTS SDK。
  2. 将rtsdec.c和rtsenc.c文件复制到FFmpeg播放器的libavformat目录中。
  3. 修改Makefile文件。

    在Makefile文件中增加rtsdec.o和rtsenc.o的描述,如下图所示:

    001
  4. 修改allformats.c文件。
    002
  5. 编译运行。

    ./ffplay -i "artc://视频URL"

Mac平台集成

  1. 下载并解压Mac端RTS SDK。
  2. 将rtsdec.c和rtsenc.c文件复制到FFmpeg播放器的libavformat目录中。
  3. 修改Makefile文件。

    在Makefile文件中增加rtsdec.o和rtsenc.o的描述,如下图所示:

    001
  4. 修改allformats.c文件。
    002
  5. 编译运行。

    ./ffplay -i "artc://视频URL"