すべてのプロダクト
Search
ドキュメントセンター

:iOS

最終更新日:Sep 05, 2024

このトピックでは、ネイティブRTS SDKをFFmpegに基づくサードパーティのプレーヤーに統合して、iOSクライアントにリアルタイムストリーミング (RTS) を実装する方法について説明します。 このトピックでは、サードパーティのプレーヤーijkplayer k0.8.8が使用されます。

前提条件

ijkplayerのソースコードはコンパイルされています。 詳細については、ijkplayerのREADME.mdファイルをご参照ください。

手順

  1. ijkplayerのソースコードをダウンロードして解凍します。 ダウンロードリンクを取得するには、ijkplayerページにアクセスしてください。

  2. ネイティブRTS SDKパッケージをダウンロードして解凍します。 ダウンロードリンクの詳細については、「SDKダウンロード」をご参照ください。

  3. ネイティブRTS SDKをプラグインとしてijkplayerに統合します。 次の表に、2つの統合方法を示します。

    統合方法

    説明

    利点

    デメリット

    FFmpegを拡張します。

    デマルチプレクサプラグインを追加してFFmpegを拡張します。

    この方法は開発を簡単にする。 Alibaba Real-Time Communication (ARTC) ベースのURL用に追加のロジックを開発する必要はありません。

    FFmpegを再コンパイルする必要があります。

    ijkplayerを拡張します。

    AVInputFormat構造体を追加してijkplayerを拡張します。

    FFmpegをコンパイルする必要はありません。

    ff_ffplay.cファイルにロジックコードを追加する必要があります。

    FFmpegを拡張する

    1. ijkplayerのルートディレクトリで、./init-ios.shコマンドを初期化します。

      Xcode 14は、ARMv7、i386、x86_64などのアーキテクチャをサポートしなくなりました。 これらのアーキテクチャのコードをinit-ios.shファイルから削除する必要があります。

      次のコンパイルスクリプトは、Xcode 14を使用する場合の例です。

      # FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64"
      FF_ALL_ARCHS_IOS11_SDK="arm64"
      FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS11_SDK
    2. ijkplayerのiOSディレクトリを開きます。 FFmpegのコマンドをコンパイルし、buildディレクトリからffmpeg-$archフォルダがiOSディレクトリに表示された場合は、. /きれいなcompile-ffmpeg.shコマンドを実行してiOSディレクトリをクリーンアップします。

    3. ネイティブRTS SDKのrtsdec.cファイルをijkplayer/ios/ffmpeg-$arch/libavformatディレクトリにコピーします。

    4. Makefileファイルを変更し、rtsdec.cファイルをコンパイルします。914

    5. allformats.cファイルを変更します。

      ijkplayer/ios/ffmpeg-$arch/libavformat/allformats.cファイルを変更します。 デフォルトでは、Alibaba Real-Time Communication (ARTC) プロトコルがサポートされています。

      016

    6. FFmpegコンパイルスクリプトijkplayer/config/module-lite.shを変更して、パルスコード変調 (PCM) デコードをサポートします。 ネイティブRTS SDKがPCMデータをエクスポートするため、この操作が必要です。

      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"

      オプション: HTTPSプロトコルでストリームをサポートする場合は、次のコードをファイルに追加してOpenSSLサポートを有効にします。

      export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl"

      のエクスポート

    7. FFmpegをコンパイルします。

      を実行します。Run the. /すべてcompile-ffmpeg.shコマンドのijkplayer/iosディレクトリに移動します。 同時に、ステップaのように、サポートされていないアーキテクチャのコードをスクリプトから削除します。 FFmpegをコンパイルした後、FFmpegコンパイルの出力ファイルがijkplayer/ios/build/universalディレクトリにあることを確認してください。

      オプション: HTTPSプロトコルを介したストリームをサポートする場合は、. /すべてcompile-openssl.shコマンドを実行します。 同時に、ステップaのように、サポートされていないアーキテクチャのコードをスクリプトから削除します。 FFmpegをコンパイルすると、libssl.aファイルとlibcrypto.aファイルがijkplayer/ios/build/universal/libディレクトリに生成されます。 次に、コンパイル. /すべてcompile-ffmpeg.sh.

    8. ネイティブRTS SDKのRtsSDK.frameworkファイルをijkplayer/ios/IJKMediaDemo/IJKMediaDemoディレクトリにコピーします。

    9. Xcodeでios/IJKMediaDemo/IJKMediaDemo.xcodeprojを開きます。

    10. RtsSDK.frameworkを依存関係として追加します。264

    11. ネイティブRTS SDKの動的フレームワークを追加します。

      ネイティブRTS SDKのヘッダーファイルrts_api.hおよびrts_messages.hをijkplayer/ios/build/universal/libディレクトリにインポートします。

      rts_api.h

    12. RTSのロジックコードをff_ffplay.cファイルに追加します。

      ヘッダーファイルrts_api.hをインポートします。

      #include "rts_api.h"

      を含める

      ARTCのAVInputFormat関数ポインターを設定して、ijkplayer/ijkmedia/ijkplayer/ff_ffplay.cファイルを変更します。AVInputFormat

      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を拡張する

    1. ijkplayerのルートディレクトリで、. /init-ios.shコマンドを初期化します。

      Xcode 14は、ARMv7、i386、x86_64などのアーキテクチャをサポートしなくなりました。 これらのアーキテクチャのコードをinit-ios.shファイルから削除する必要があります。

      次のコンパイルスクリプトは、Xcode 14を使用する場合の例です。

      # FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64"
      FF_ALL_ARCHS_IOS11_SDK="arm64"
      FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS11_SDK
    2. ijkplayerのiOSディレクトリを開きます。 FFmpegのコマンドをコンパイルし、buildディレクトリからffmpeg-$archフォルダがiOSディレクトリに表示された場合は、./compile-ffmpeg.sh cleanコマンドを実行してiOSディレクトリをクリーンアップします。

    3. FFmpegコンパイルスクリプトijkplayer/config/module-lite.shを実行して、PCMデコードをサポートします。 ネイティブRTS SDKがPCMデータをエクスポートするため、この操作が必要です。

      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"

      オプション: HTTPSプロトコルでストリームをサポートする場合は、次のコードをファイルに追加してOpenSSLサポートを有効にします。

      export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl"

      のエクスポート

    4. FFmpegをコンパイルします。

      ijkplayer/iosディレクトリにある./compile-ffmpeg.sh allを実行します。同時に、ステップaのように、サポートされていないアーキテクチャのコードをスクリプトから削除します。 FFmpegをコンパイルした後、FFmpegコンパイルの出力ファイルがijkplayer/ios/build/universalディレクトリにあることを確認してください。

      オプション: HTTPSプロトコルを介したストリームをサポートする場合は、./compile-ffmpeg.sh allコマンドを実行します。 同時に、ステップaのように、サポートされていないアーキテクチャのコードをスクリプトから削除します。 FFmpegをコンパイルすると、libssl.aファイルとlibcrypto.aファイルがijkplayer/ios/build/universal/libディレクトリに生成されます。 次に、コンパイル./compile-ffmpeg.sh all.

    5. ネイティブRTS SDKのRtsSDK.frameworkファイルをijkplayer/ios/IJKMediaDemo/IJKMediaDemoディレクトリにコピーします。

    6. ネイティブRTS SDKのrtsdec.cファイルをプロジェクトにインポートします。270

      ネイティブRTS SDKのヘッダーファイルrts_api.hおよびrts_messages.hをijkplayer/ios/build/universal/libディレクトリにインポートします。

      rts_api.h

    7. RTSのロジックコードをff_ffplay.cファイルに追加します。

      ヘッダーファイルrts_api.hをインポートします。

      #include "rts_api.h"

      を含める

      ARTCのAVInputFormat関数ポインターを設定して、ijkplayer/ijkmedia/ijkplayer/ff_ffplay.cファイルを変更します。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);
      }
  4. IJKMediaPlayerプロジェクトをコンパイルします。

    FFmpegまたはijkplayerを拡張した後、アーカイブコンパイラを使用してijkplayer/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeprojプロジェクトを実行します。 IJKMediaFramework.frameworkファイルは、Productsディレクトリに生成されます。

    オプション: HTTPSプロトコルでストリームをサポートする場合は、コンパイルを実行する前に、XcodeでプロジェクトのBuild Phases > Link Binary With Librariesを選択し、前の手順で生成されたlibssl.aおよびlibcrypto.aファイルをijkplayer/ios/build/universal/libディレクトリにインポートします。

    IJKMediaPlayer

  5. Native RTS SDKのRtsSDK.frameworkファイルとijkplayerのIJKMediaFramework.frameworkファイルをプロジェクトに挿入します。

    273

  6. ijkplayerによって提供されるメソッドを呼び出して、RTS機能を使用します。

    • ijkplayerの作成

      // Generate a URL over the ARTC protocol.
      _url = @"artc://xxxx";
      
      // Create a custom playerView.
      [self.view addSubview:self.playerView];
      ...
      
      IJKFFOptions *options = [IJKFFOptions optionsByDefault];
      // Configure hardware decoding.
      [options setPlayerOptionIntValue:1 forKey:@"videotoolbox"];
      // Configure software decoding.
      //[options setPlayerOptionIntValue:0 forKey:@"videotoolbox"];
      
      _ijkPlayer = [[IJKFFMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:_url] withOptions:options];
      _ijkPlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
      _ijkPlayer.view.frame = self.playerView.bounds;
      _ijkPlayer.scalingMode = IJKMPMovieScalingModeAspectFit; // Specify the scaling mode.
      _ijkPlayer.shouldAutoplay = YES; // Enable autoplay.
      [self.playerView addSubview:_ijkPlayer.view];
    • セット再生コントロール

      • 再生を開始します。

        メインスレッドでメソッドを呼び出す必要があります。 毎回再生を再開する前に、再生を停止してプレーヤーをリリースすることをお勧めします。

        dispatch_async(dispatch_get_main_queue(), ^{
            [_ijkPlayer prepareToPlay];
            [_ijkPlayer play];
        });
      • 再生を停止し、プレーヤーを解放します。

        // Stop playback.
        [_ijkPlayer stop];
        
        // Release the player.
        [_ijkPlayer shutdown];
        _ijkPlayer = nil;

RTSイベントを聴く

  • ijkplayerでNative RTS SDKのメッセージコールバックを聞く

    ijkplayer/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeprojプロジェクトを開き、適合したメソッドを関連ファイルに追加します。

    1. static int audio_open(FFPlayer * opaque、int64_t wanted_channel_layout、int wanted_nb_channels、int wanted_sample_rate、struct AudioParams * audio_hw_params){} メソッドの後に次のコードブロックを挿入して、ff_ff_ffplay.cファイルを変更します。

      extern int artcDemuxerMessage(struct AVFormatContext *s, int type, void *data, size_t data_size);
      //aliyun rts:receive artc message
      int onArtcDemuxerMessage(struct AVFormatContext *s, int type, void *data, size_t data_size)
      {
          return artcDemuxerMessage(s, type, data, data_size);
      }
      
      int artcDemuxerMessage(struct AVFormatContext *s, int type, void *data, size_t data_size)
      {
          //aliyun rts:send message to app
          FFPlayer *ffp = (FFPlayer *)s->opaque;
          const char *data_msg = (const char *)data;
          ffp_notify_msg4(ffp,FFP_MSG_ARTC_DIRECTCOMPONENTMSG,type,0,data_msg,data_size);
          return 0;
      }
    2. static int is_realtime(AVFormatContext * s){} メソッドに次のRTSコードブロックを挿入して、ff_ffplay.cファイルを変更します。

      static int is_realtime(AVFormatContext *s)
      {
          if(   !strcmp(s->iformat->name, "rtp")
             || !strcmp(s->iformat->name, "rtsp")
             || !strcmp(s->iformat->name, "sdp")
             // *** Beginning of the RTS code block ***
             || !strcmp(s->iformat->name, "artc")
             // *** End of the RTS code block ***
          )
              return 1;
      
          if(s->pb && (   !strncmp(s->filename, "rtp:", 4)
                       || !strncmp(s->filename, "udp:", 4)
                      )
          )
              return 1;
          return 0;
       }                           
    3. static int read_thread(void * arg){} メソッドに次のRTSコードブロックを挿入して、ff_ffplay.cファイルを変更します。

      static int read_thread(void *arg)
      {
        ......
        ic = avformat_alloc_context();
        if (!ic) {
          av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");
          ret = AVERROR(ENOMEM);
          goto fail;
        }
      
        // *** Beginning of the RTS code block ***
        ic->opaque = ffp;
        ic->control_message_cb = onArtcDemuxerMessage;
        // *** End of the RTS code block ***
      
        ......
        if (ffp->skip_calc_frame_rate) {
           av_dict_set_int(&ic->metadata, "skip-calc-frame-rate", ffp->skip_calc_frame_rate, 0);
           av_dict_set_int(&ffp->format_opts, "skip-calc-frame-rate", ffp->skip_calc_frame_rate, 0);
        }
      
        // *** Beginning of the RTS code block ***
        if(strncmp(is->filename, "artc://", 7) == 0) {
           extern AVInputFormat ff_rtc_demuxer;
           is->iformat = &ff_rtc_demuxer;
        } else {
           if(ffp->iformat_name)
             is->iformat = av_find_input_format(ffp->iformat_name);
         }
        // *** End of the RTS code block ***
        ......
        pkt->flags = 0;
        // *** Beginning of the RTS code block ***
        if(strncmp(is->filename, "artc://", 7) == 0) {
            bool videoExist = is->video_stream >= 0;
          bool audioExist = is->audio_stream >= 0;
          // av_log(NULL, AV_LOG_INFO, "videoDuration %lld audioDuration %lld rate %f videoframeQue %d audioFrameque %d\n",
          // is->videoq.duration, is->audioq.duration, ffp->pf_playback_rate,
          // frame_queue_nb_remaining(&is->pictq), frame_queue_nb_remaining(&is->sampq));
          if(!videoExist) {
             if(is->audioq.duration > 300 ) { // accelerate
                 if(ffp->pf_playback_rate <= 1.0) {
                     ffp->pf_playback_rate = 1.3;
                     ffp->pf_playback_rate_changed = 1;
                     av_log(NULL, AV_LOG_INFO, "aliyun rts set rate to %f\n", ffp->pf_playback_rate);
                 }
             }
             else if(is->audioq.duration < 200) { // restore speed
                 if(ffp->pf_playback_rate > 1.0) {
                     ffp->pf_playback_rate = 1.0;
                     ffp->pf_playback_rate_changed = 1;
                     av_log(NULL, AV_LOG_INFO, "aliyun rts restore rate 1.0\n");
                  }
             }
          }
          else if((!videoExist || (videoExist && is->videoq.duration > 300)) && (!audioExist || (audioExist && is->audioq.duration > 300))) {
             if(ffp->pf_playback_rate <= 1) {
                 ffp->pf_playback_rate = 1.3;
                 ffp->pf_playback_rate_changed = 1;
                 av_log(NULL, AV_LOG_INFO, "aliyun rts set rate 1.1\n");
             }
          } else if((videoExist && is->videoq.duration <= 100) ||  (audioExist && is->audioq.duration <= 100)){
             if(ffp->pf_playback_rate > 1) {
                 ffp->pf_playback_rate = 1;
                 ffp->pf_playback_rate_changed = 1;
                 av_log(NULL, AV_LOG_INFO, "aliyun rts set rate 1\n");
              }
          }
        }
        // *** End of the RTS code block ***
        ......
      }
    4. RTSメッセージのメソッド宣言を追加してff_ffmsg.hファイルを変更します。

      #define FFP_MSG_ARTC_DIRECTCOMPONENTMSG     3000
    5. RTSメッセージを上位層に送信します。

      • RTSメッセージの外部呼び出しをリッスンするリスナーの宣言を追加して、IJKMediaPlayback.hファイルを変更します。

        IJK_EXTERN NSString *const IJKMPMoviePlayerRtsMsgNotification;
      • RTSメッセージの外部呼び出しをリッスンするリスナーの定義を追加して、IJKMediaPlayback.mファイルを変更します。

        NSString *const IJKMPMoviePlayerRtsMsgNotification = @"IJKMPMoviePlayerRtsMsgNotification";
      • リスナーから返されたRTSメッセージを処理するためにpostEvent: メソッドを呼び出すことができるように、IJKFFMoviePlayerController.mファイルを変更します。

        - (void)postEvent: (IJKFFMoviePlayerMessage *)msg
        {
            ......
          case FFP_MSG_ARTC_DIRECTCOMPONENTMSG:{
             NSString *rtsMsg = [[NSString alloc] initWithUTF8String:avmsg->obj];
             int type = avmsg->arg1;
             if (!rtsMsg) {
                rtsMsg = @"";
             }
             NSDictionary *dic = @{@"type":@(type),@"msg":rtsMsg};
             [[NSNotificationCenter defaultCenter] postNotificationName:IJKMPMoviePlayerRtsMsgNotification
                            object:dic];
             break;
            }
           default:
             // NSLog(@"unknown FFP_MSG_xxx(%d)\n", avmsg->what);
             break;
        }
      • アーカイブコンパイラを使用してIJKMediaPlayer.xcodeprojプロジェクトを実行し、最新のIJKMediaFramework.frameworkファイルを取得します。

  • ijkplayerでネイティブRTS SDKの再試行を実行するために使用するメソッドを追加する

    1. rts_reload_flag変数の定義を追加して、ff_ffplay.hファイルを変更します。

      int       rts_reload_flag;
    2. static int audio_open(FFPlayer * opaque、int64_t wanted_channel_layout、int wanted_nb_channels、int wanted_sample_rate、struct AudioParams * audio_hw_params){} メソッドの後に次のコードブロックを挿入して、ff_ff_ffplay.cファイルを変更します。

      extern int artc_reload(AVFormatContext *ctx);
      
      void ffp_rts_reload(FFPlayer *ffp){
         if(rts_reload_flag == 0)
         {
            rts_reload_flag = 1;
         }
      }
    3. static int read_thread(void * arg){} メソッドに次のRTSコードブロックを挿入して、ff_ffplay.cファイルを変更します。

      static int read_thread(void *arg)
      {
           ......
      #ifdef FFP_MERGE
         if (is->paused != is->last_paused) {
            is->last_paused = is->paused;
            if (is->paused)
               is->read_pause_return = av_read_pause(ic);
             else
                av_read_play(ic);
         }
      #endif
         // *** Beginning of the RTS code block ***
         if(rts_reload_flag){
              rts_reload_flag = 0;
              av_log(ffp, AV_LOG_ERROR, "param  == ffp_rts_reload\n");
              VideoState *is = ffp->is;
              AVFormatContext *ic = is->ic;
              artc_reload(ic);
          }
         // *** End of the RTS code block ***
         ......
      }
    4. ijkmp_rts_reloadメソッドの定義を追加して、ijkplayer.hファイルを変更します。

      void            ijkmp_rts_reload(IjkMediaPlayer *mp);
    5. ijkplayer.cファイルを変更して、ijkmp_rts_reloadメソッドを実装します。

      void ijkmp_rts_reload(IjkMediaPlayer *mp)
      {
          ffp_rts_reload(mp->ffplayer);
      }
    6. rtsReloadメソッドを上位レイヤーに追加します。

      • rtsReloadメソッドの外部呼び出しの宣言を追加して、IJKFFMoviePlayerController.hファイルを変更します。

        - (void)rtsReload;
      • IJKFFMoviePlayerController.mファイルを変更して、rtsReloadメソッドの外部呼び出しを実装します。

        - (void)rtsReload {
            ijkmp_rts_reload(_mediaPlayer);
        }
      • アーカイブコンパイラを使用してIJKMediaPlayer.xcodeprojプロジェクトを実行し、最新のIJKMediaFramework.frameworkファイルを取得します。

  • 劣化したプロトコルを介してライブストリームへのRTSメッセージコールバックをリッスンするためのメソッドを呼び出す

    • RTSメッセージのコールバックをリッスンします。

      [[NSNotificationCenter defaultCenter] addObserver:self
                                               selector:@selector(reviceMsg:)
                                                   name:IJKMPMoviePlayerRtsMsgNotification
                                                 object:nil];
    • RTSメッセージのコールバックをリッスンするために使用されるメソッドに、劣化ロジックを実装します。

      ソースURLのプレフィックスをartc:// からrtmp:// に変更するか、URLをhttp:// xxxx.flv形式に変換してから、ApsaraVideo PlayerのUrlSourceを更新できます。 これにより、劣化したプロトコルを使用してライブストリームを再生できます。

      // Use a degraded protocol, such as http://xxx.flv or rtmp://xxx, for live streaming.
      - (void)convertArtcToRtmpPlay {
          // Obtain the streaming URL and intercept the prefix of the URL.
          NSArray *urlSeparated = [self.url componentsSeparatedByString:@"://"];
          NSString *urlPrefix = urlSeparated.firstObject;
          // Check whether the prefix of the URL is artc. If the prefix is artc, you can use a degraded protocol for standard streaming.
          if ([urlPrefix isEqualToString:@"artc"]) {
              // http://xxx.flv (recommended)
              _url = [[@"http://" stringByAppendingString:urlSeparated.lastObject] stringByAppendingString:@".flv"];
              // rtmp://xxx
              // _url = [@"rtmp://" stringByAppendingString:urlSeparated.lastObject];
      
                  // Stop playback and destroy the player.
            [_ijkPlayer stop];
            [_ijkPlayer shutdown];
            _ijkPlayer = nil;
      
            // Re-set the playback source.
            _ijkPlayer = [[IJKFFMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:_url] withOptions:options];
            ......
                  // Start playback.
            dispatch_async(dispatch_get_main_queue(), ^{
                      [_ijkPlayer prepareToPlay];
                      [_ijkPlayer play];
                  });
          }
      }

      事前にRtsSDK APIをインポートする必要があります。

      #import <RtsSDK/rts_messages.h>

      次に、プレイヤーイベントのコールバックを処理します。

      -(void)reviceMsg:(NSNotification*)notification{
          NSDictionary *dic = [notification object];
        NSNumber *type = dic[@"type"];
        switch (type.intValue) {
          case E_DNS_FAIL:
          case E_AUTH_FAIL:
          case E_CONN_TIMEOUT:
          case E_SUB_TIMEOUT:
          case E_SUB_NO_STREAM:
          {
            // Perform degradation.
            [self convertArtcToRtmpPlay];
          }
              break;
          case E_STREAM_BROKEN:
          {
             static BOOL retryStartPlay = YES;
             // The first time the RTS media times out, retry playback once. If the RTS media still times out, use a degraded protocol for playback.
             if (retryStartPlay) {
                 dispatch_async(dispatch_get_main_queue(), ^{
                   [_ijkPlayer rtsReload];
                   });
                 retryStartPlay = NO;
              } else {
                 // Perform degradation.
                 [self convertArtcToRtmpPlay];
              }
           }
            break;
          case E_RECV_STOP_SIGNAL:
                  {
                // Stop playback and destroy the player.
                [_ijkPlayer stop];
              [_ijkPlayer shutdown];
              _ijkPlayer = nil;
            }
            break;
          default:
            break;
        }
      }