Skip to content

Conversation

@t-miya
Copy link
Contributor

@t-miya t-miya commented Dec 9, 2025

iOS SDK での音声ハードミュートのため、pauseRecording()/resumeRecording() を追加します

RTCPeerConnectionFactory

init 時に AudioDeviceModule を受け取るパスを追加しました。
用途として RTCAudioDeviceModule のポインタを保持しライフサイクル管理します。
既存の DeviceModule を受け取るパスも維持しています。

RTCAudioDeviceModule(新規)

AudioDeviceModuleIOS を生成し、pauseRecording()/resumeRecording() するためのラッパーとして今回追加しました。

AudioDeviceModuleIOS

pauseRecording()/resumeRecording() を追加しました。
AudioDeviceIOS の pauseRecording()/resumeRecording() を呼び出します。

AudioDeviceIOS

追加

paused_recording_ フラグを追加して録音停止中であることを管理します。
pauseRecording() では recording_.store(0, std::memory_order_release); で録音フラグを OFF にします。
resumeRecording() では paused_recording_ を false にした上で startRecording() を実行して録音を再開します。

既存の修正

startRecording() はポーズ中 paused_recording_=true で呼ばれた場合は resumeRecording() にフォールスルーするようにしています。
stopRecording() では録音ポーズ中に呼ばれることがあるため paused_recording_ のチェックを追加して、録音停止中でも paused_recording_=true の場合は解放処理を行うようにしています。

@t-miya

This comment was marked as abuse.

@t-miya

This comment was marked as abuse.

@github-actions

This comment was marked as resolved.

@t-miya

This comment was marked as resolved.

@github-actions

This comment was marked as resolved.

@t-miya

This comment was marked as abuse.

@github-actions

This comment was marked as resolved.

@t-miya t-miya requested a review from melpon December 9, 2025 09:06
@melpon
Copy link
Contributor

melpon commented Dec 9, 2025

  • RTCAudioSession.h に pauseRecording, resumeRecording を生やしているけど、これはオーディオセッションとは何の関係もない
  • g_last_audio_device_module_ios というグローバル変数を使っているが、複数の PeerConnectionFactory を生成したら破綻する

ので設計を見直した方が良さそうです。

調べた限り ADM は ObjC 側に公開されていないので、

  • RTCAudioDeviceModule.{h,mm} を新しく作り、そこの初期化時に AudioDeviceModuleIOS を生成して保持しておき、メソッドとして pauseRecording, resumeRecording を生やしておく(本当は ADM が必要とするメソッド全部用意するべきだけど大変過ぎるので最低限だけ)
    • 多分 RTCAudioDeviceModule+Native.h みたいなのも必要になるはずなので、適宜作る
  • RTCPeerConnectionFactory に initWithEncoderFactory:decoderFactory:audioDeviceModule: を生やして、RTCAudioDeviceModule から webrtc::AudioDeviceModule を取得して dependencies.adm に設定する

という感じにすれば RTCAudioDeviceModule の関数を呼んで pauseRecording, resumeRecording が出来そうです。

こうすると、iOS SDK 側の NativePeerChannelFactory.swift#L44-L47 あたりで

    adm = RTCAudioDeviceModule()
    nativeFactory =
      RTCPeerConnectionFactory(
        encoderFactory: encoder,
        decoderFactory: decoder,
        audioDeviceModule: adm)

みたいに書けて、あとは adm を適切に使えば iOS SDK から pause/resume できるようになるはず。

@t-miya
Copy link
Contributor Author

t-miya commented Dec 10, 2025

RTCAudioDeviceModule を追加する方向で修正します

@t-miya

This comment was marked as resolved.

@github-actions

This comment was marked as abuse.

@t-miya

This comment was marked as resolved.

@github-actions

This comment was marked as resolved.

@melpon
Copy link
Contributor

melpon commented Dec 10, 2025

シングルトンパターン: RTCAudioDeviceModule のシングルトンパターン実装は、単一ADMシナリオを優雅に処理し、前述のグローバル変数の問題を回避しています。

何も回避できてないです。シングルトンはグローバル変数と同じです。

@t-miya
Copy link
Contributor Author

t-miya commented Dec 11, 2025

シングルトンを避ける方向で再度見直し中です

@t-miya

This comment was marked as resolved.

@github-actions

This comment was marked as resolved.

@t-miya

This comment was marked as resolved.

@github-actions

This comment was marked as resolved.

@melpon
Copy link
Contributor

melpon commented Dec 11, 2025

WeakPtr 関連は無くても平気なはずです。今までは RTCPeerConnectionFactory が解放された時に ADM が解放されてたのが、RTCPeerConnectionFactory と RTCAudioDeviceModule の両方が解放された時に ADM が解放されるようになるだけです。

@t-miya
Copy link
Contributor Author

t-miya commented Dec 11, 2025

なるほど。了解です。

@t-miya t-miya force-pushed the feature/ios-audio-pause-resume branch from cda9dea to 9359604 Compare December 12, 2025 04:24
@t-miya

This comment was marked as resolved.

@github-actions

This comment was marked as resolved.

@t-miya
Copy link
Contributor Author

t-miya commented Dec 12, 2025

@melpon
WeakPtr を外す対応しました。その他も対応済みのため再度レビューお願いします🙏

+ decoderFactory
+ audioDevice:(nullable id<RTC_OBJC_TYPE(RTCAudioDevice)>)audioDevice
+ audioDeviceModule:
+ (nullable RTC_OBJC_TYPE(RTCAudioDeviceModule)*)audioDeviceModule;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この関数は不要そう

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

audioDevice、audioDeviceModule 両方を引数に取る版は削除して、元の実装を維持しつつ
audioDeviceModule 引数版を追加するように修正しました

+ // RTCAudioDeviceModule は内部でネイティブ ADM を生成・保持する(scoped_refptr による所有)
+ // RTCPeerConnectionFactory は初期化時に RTCAudioDeviceModule から生ポインタを受け取る
+ // RTCAudioDeviceModule が破棄されると内部 ADM も破棄される
+ __weak RTC_OBJC_TYPE(RTCAudioDeviceModule)* _objcAudioDeviceModule;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここに ADM 保持する意味ないです

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_objcAudioDeviceModule; メンバーを削除しました


/* Initialize object with injectable video encoder/decoder factories and
- * injectable ADM */
+ * injectable ADM (RTCAudioDevice) */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここの変更は不要そう

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

変更を元に戻しました

+- (instancetype)init;
+
+// ネイティブ ADM を取得する(所有権移動なし、未初期化なら nullptr)
+- (void *)getNativeAudioDeviceModule;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このメソッドは iOS SDK に公開されるヘッダーなんですが、

  • 正しいポインタに戻す方法が無い
  • そもそも公開する側で使うメソッドではない

ので使い道が無いです。RTCAudioDeviceModule+Private.h とかそういうファイルを作って、ちゃんと型を明示して C++ から参照できる形にして下さい

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RTCAudioDeviceModule+Private.h を作成し、nativeAudioDeviceModule 定義を移動しました

+// 内部で AudioDeviceModuleIOS を生成する
+- (instancetype)init;
+
+// ネイティブ ADM を取得する(所有権移動なし、未初期化なら nullptr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コンストラクタで ADM を生成するので未初期化状態にはならないはずです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null チェック含めて修正しました

+- (BOOL)pauseRecording {
+ auto ptr =
+ static_cast<webrtc::ios_adm::AudioDeviceModuleIOS*>(_adm_owner.get());
+ if (!ptr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nullptr にはならないはずです

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このチェックを外しました

+ if (!ptr) {
+ return NO;
+ }
+ return ptr->PauseRecording() == 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このクラスは webrtc::AudioDeviceModule の ObjC 版なので、変換をせずにそのまま整数で返すべきです

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

呼び出しそのままの値を返すようにしました。関数返り値型を NSInteger に変更しました

+ // InitRecording に失敗した場合は pause 状態の解除も recording_ の再立て直しも行えないため
+ // 上位にエラーを返す
+ if (!audio_is_initialized_) {
+ if (InitRecording() != 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resume 時にまだ Init してない場合に Init してあげる必要ありますかね?ちょっとどういう使い方を想定してるのか分からないです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここではフラグ操作のみにしました

return 0;
}

+int32_t AudioDeviceIOS::PauseRecording() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PauseRecording/ResumeRecording って、StartRecording/StopRecording と何が違うんでしょうか。見てる感じ StartRecording と StopRecording だけで事足りるように見えます

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StopRecording は内部で ShutdownPlayOrRecord() によりデバイス解放する部分が異なっています

ResumeRecording() は直接 StartRecording() を呼んでよいかもしれないです。確認します

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AudioDeviceIOS 内の PauseRecording/ResumeRecording は recording_ フラグの操作のみを行い、
startRecording() 等を呼ばないように修正しました

}

-AudioDeviceModuleIOS::~AudioDeviceModuleIOS() {
+int32_t AudioDeviceModuleIOS::AttachAudioBuffer() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このあたりどうなってるんだろ、不要な変更に見えます

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

関数の順番だけ入れ替わった不要な変更になっていたので戻しました

@t-miya
Copy link
Contributor Author

t-miya commented Dec 15, 2025

@melpon
指摘いただいた箇所修正しましたのでレビューお願いします🙏

}

- rtc_library("core_audio_helpers_objc") {
+rtc_library("core_audio_helpers_objc") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

インデントが消えてる?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ずれてしまっていたので修正しました

(nullable id<RTC_OBJC_TYPE(RTCAudioDevice)>)audioDevice;

+/* Initialize object with injectable video encoder/decoder factories and
+ * RTCAudioDeviceModule (pause/resume 用) */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これ Javadoc 形式でも無いし、普通の C コメントでもない中途半端な書き方なので統一して欲しいです。あと日本語で書いて下さい。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメント形式を直して日本語で書き直しました

dependencies.env = webrtc::CreateEnvironment();
-#ifdef WEBRTC_IOS
- dependencies.adm = webrtc::CreateAudioDeviceModule(*dependencies.env);
-#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これは消す必要無さそうに見えます

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

消す必要なかったですね。戻しました

+ dependencies.video_decoder_factory =
+ webrtc::ObjCToNativeVideoDecoderFactory(decoderFactory);
+ }
+#ifdef WEBRTC_IOS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS でしかパッチを当てないので ifdef は不要そう

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そもそもパッチターゲットがあるのを失念してました

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RTCAudioDeviceModule を引数に取る initWithEncoderFactory では #ifdef WEBRTC_IOS を削除しました

+#ifdef WEBRTC_IOS
+ if (audioDeviceModule) {
+ auto adm_ptr = [audioDeviceModule nativeAudioDeviceModule];
+ if (adm_ptr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adm_ptr が nullptr になることは無いはずです

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

その通りなので adm_ptr の null チェックは外しました

+- (instancetype)init;
+
+// 録音を一時停止/再開する
+// 内部で AudioDeviceModuleIOS -> AudioDeviceIOS の pauseRecording()/resumeRecording() を呼び出す
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

内部のことについて書くのはまあ良いとしても、AudioDeviceModuleIOS が AudioDeviceIOS の関数を呼んでいるかどうかに関してはこのクラスは知らない話なので書くべきではないです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AudioDeviceIOS 部分のコメントを削除して、AudioDeviceModuleIOS の pauseRecording() を呼ぶ、までにしました
また resumeRecording() とそれぞれコメントを分離しました

+#import "RTCAudioDeviceModule.h"
+#include <objc/NSObjCRuntime.h>
+
+#include <arm_acle.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このヘッダー何に使ってるんだろ。不要に見えます。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不要でした。削除しました

+ return self;
+}
+
+#ifdef __cplusplus
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.mm ファイルなのでこの #ifdef いらないです

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

削除しました

if (!playing_.load()) {
ShutdownPlayOrRecord();
}
+ if (recording_.load()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この分岐必要なさそう

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

録音フラグ操作が二重で走っても問題ないので不要でした

return 0;
}
- audio_device_buffer_.get()->StartRecording();
+ if (audio_device_buffer_) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このパッチで audio_device_buffer_ が nullptr になる可能性が増えてるようには見えないので修正する必要無さそうに見えます。他の分岐も同様です。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

startRecording()/stopRecording() 含めて audio_device_buffer_ の null チェックを外しました
また関数の呼び出しを audio_device_buffer_.get()-> で統一しました

@class RTC_OBJC_TYPE(RTCVideoSource);
@class RTC_OBJC_TYPE(RTCVideoTrack);
@class RTC_OBJC_TYPE(RTCPeerConnectionFactoryOptions);
+@class RTC_OBJC_TYPE(RTCAudioDeviceModule);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@protocol~ の下に置いていたのを @class~ の並びの方に移動しました

sources += [
"objc/helpers/UIDevice+RTCDevice.h",
"objc/helpers/UIDevice+RTCDevice.mm",
+ "objc/components/audio/RTCAudioDeviceModule.mm",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

現状では audio components 関連は RTCAudioDeviceModule のみのため新たにターゲットは切らずここに置く

@t-miya
Copy link
Contributor Author

t-miya commented Dec 17, 2025

@melpon
再度修正しましたのでご確認お願いします🙏

CHANGES.md Outdated

- 2025-12-12 [ADD] iOS SDK に RTCAudioDeviceModule を追加する
- iOS 実機のマイクインジケータが消灯状態のミュートをできるようにする
- RTCPeerConnectionFactory に RTCAudioDeviceModule を引数とする initWithEncoderFactory() を追加する
Copy link
Contributor

@melpon melpon Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ObjC の場合これは initWithEncoderFactory:decoderFactory:audioDeviceModule: というメソッド名になります。
引数の名前まで含めてメソッド名で、C++ みたいな引数の型によるオーバーロードは存在しないです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initWithEncoderFactory:decoderFactory:audioDeviceModule: に修正しました。
その他コメント中で pauseRecording() のように書いていた箇所を pauseRecording 等に修正しました。

Copy link
Contributor

@melpon melpon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

よさそう

@t-miya
Copy link
Contributor Author

t-miya commented Dec 17, 2025

ありがとうございました🙇

@t-miya t-miya merged commit 857a55f into feature/m143.7499 Dec 17, 2025
15 checks passed
@t-miya t-miya deleted the feature/ios-audio-pause-resume branch December 17, 2025 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants