shiguredo / sora-ios-sdk

WebRTC SFU Sora iOS SDK
https://sora-ios-sdk.shiguredo.jp/
Apache License 2.0
42 stars 8 forks source link

MediaStream#send時にEXC_BAD_ACCESS(code=1, address=xxxxx)が発生する #41

Closed soudegesu closed 4 years ago

soudegesu commented 4 years ago

サマリ

Sora iOS SDK 2020.4 において、MediaStream.swift#sendにて EXC_BAD_ACCESS(code=1, address=xxxxx) が発生します。なお、 2020.3 では発生していません。

環境

期待する動作、現象

EXC_BAD_ACCESSが発生せずに、フレームの送信ができること

実際の動作、現象

MediaStream.swift#send: L273 が直接的な発生箇所になります。根本原因はまだ探れていません。

nativeVideoSource?.capturer(capturer ?? BasicMediaStream.dummyCapturer, didCapture: nativeFrame)

再現手順

以下2種類のクライアントから同じチャンネルに対して以下条件にて接続を行いました。

  1. iOS端末

    • role: sendonly
    • videoCodec: h264
    • videoCapturerOption: .custom
    • videoBitrate: 4096
    • metadata: 認可用のメタデータ
    • videoEnabled: true
    • audioEnabled: true
    • multistreamEnabled: true
  2. PCブラウザ ( Mac / Chrome / Sora JavaScript SDK 1.16.0 )

    • role: sendrecv
    • videoCodec: VP8
    • videoBitrate: 4096
    • audioCodec: OPUS
    • audioBitrate: 510
    • multistream: true
    • simulcast: true
    • simulcastQuarity: middle
    • metadata: 認可用のメタデータ

なお、 iOS → Web の順番でチャンネルに参加する(チャンネルに最初に入る)と問題ないのですが、 Web → iOSの順番でチャンネルに参加する(チャンネルに後から入る)とよく起きるように見受けられます。

szktty commented 4 years ago

@soudegesu ご報告頂きありがとうございます。 こちらも次のリリースで早急に対応します。申し訳ありません。

szktty commented 4 years ago

@soudegesu videoCapturerOption: .custom とありますが、デフォルトの映像キャプチャ (端末のカメラ) を使ってもクラッシュしますでしょうか?上記の設定で確認しましたが、デフォルトの映像キャプチャでも .custom でも再現できていません。

おそらく VideoCapturer のカスタム実装を用意されていると思われますが、もし .custom 時のみのクラッシュするのであれば実装を (VideoFrame を独自に生成しているのであれば VideoFrame の内容も) 確認してみてください。よろしければ、可能な範囲でコードをご提示頂けると助かります。

szktty commented 4 years ago

@soudegesu 追加です。 MediaStream.videoFilter にフィルターのカスタム実装をセットしているのであれば、そちらの実装も確認してみてください。

soudegesu commented 4 years ago

@szktty ご確認ありがとうございます。

コメント頂きました後に改めてiOS SDKのソースも含めて確認を致しましたところ、対処方法を確認できましたため、共有させていただきます。

videoCapturerOption: .custom 」 、かつ、「先に別のクライアントが既にチャンネルに接続している」場合、MediaChannel#senderStreamMediaChannel#mainStream のいずれの呼び出しでも VideoFrameの送信に用いる Sora.MediaStream が取得できなかったことが直接的な原因でした。

当方のVideoフレームの送信部分の実装は sora-ios-sdk-samplesの SoraSDKManager を概ね参考にさせていただいておりますため、以下のようにSoraSDKManagerを使用することで、本来使いたい Sora.MediaStream を得ることができました。

guard let currentMediaChannel = SoraSDKManager.shared.currentMediaChannel,
  let mainStream = currentMediaChannel.peerChannel.streams.first(where: { stream -> Bool in
       stream.streamId == stream.peerChannel.configuration.publisherStreamId
  }) else {
      return
  }
mainStream.send(videoFrame: frame)

当方が 2020.4 のリリースノートから、 role: .sendonly の場合には送信用の Sora.MediaStream しか入ってこないだろう、と早合点してしまったのが良くありませんでした。お手数おかけし申し訳ございませんでした。

以下は参考情報となってしまいますが、コメントいただきました件について回答させていただきます。

szktty commented 4 years ago

@soudegesu フィードバックありがとうございます。

当方が 2020.4 のリリースノートから、 role: .sendonly の場合には送信用の Sora.MediaStream しか入ってこないだろう、と早合点してしまったのが良くありませんでした。

いえ、こちらは iOS SDK の実装とドキュメントが不十分で申し訳ありませんでした。現在の実装ではカメラの映像を送信するストリームを返していますが、キャプチャのカスタマイズを考慮していませんでした。また、デフォルトのキャプチャでもクラッシュする件は Broadcast Upload Extension が関連している可能性があります。実装を見直します。

映像フレームを不適切なストリームに送信した場合にクラッシュするのは libwebrtc の問題かもしれません。その場合は iOS SDK でのフォローが難しいと思われますが、ドキュメントに注意事項を追記する予定です。

次バージョンをリリースしたらお知らせします。少々お待ち頂けると幸いです。

szktty commented 4 years ago

@soudegesu MediaChannel.senderStreamMediaChannel.receiverStreams を修正した 2020.4.1 をリリースしました。 Configuration.publisherStreamId と一致するストリーム ID を持つストリームを配信ストリームとして扱いますので、ご提示頂いたコードは次のように簡潔に表現できると思います。

SoraSDKManager.shared.currentMediaChannel.senderStream?.send(videoFrame: frame)

フィードバックありがとうございました。

soudegesu commented 4 years ago

ご対応いただきありがとうございます。 2020.4.1 へアップグレード後、ご教示いただいた実装にてフレームが送信されることを確認できました。 本issueはクローズさせていただきます。