1. 導入
[WEBRTC-NV-USE-CASES] 文書は、次のユースケースを記述している
-
信頼されていない JavaScript クラウド会議
この仕様はエンコード済みメディアへのアクセスを提供する。 これは、コーデックのエンコーダー部分の出力であり、 コーデックのデコーダー部分への入力であって、ユーザーエージェントが暗号化を ローカルで適用できるようにするものである。
このインターフェイスは [WEBCODECS] に着想を得ており、 RTCPeerConnection のセットアップフローを維持しつつ、 そのような機能へのアクセスを提供する。
2. 仕様
Streams の定義は WebIDL をあまり使用しないが、WebRTC 仕様は使用する。 この仕様は WebRTC の IDL 拡張を示す。
これは RTCRtpSender
および RTCRtpReceiver
上の追加 API を用いて、
処理をパイプラインへ挿入する。
typedef (RTCRtpSFrameEncrypter or RTCRtpScriptTransform );RTCRtpSenderTransform typedef (RTCRtpSFrameDecrypter or RTCRtpScriptTransform ); // New methods for RTCRtpSender and RTCRtpReceiverRTCRtpReceiverTransform partial interface RTCRtpSender {attribute RTCRtpSenderTransform ?transform ; };partial interface RTCRtpReceiver {attribute RTCRtpReceiverTransform ?transform ; };
この API は、RTCRtpSender
の
基盤となる エンコーダーとパケタイザーの処理ステップ間、および/または
RTCRtpReceiver
の
基盤となる デパケタイザー
と デコーダーの間のメディア
パイプラインにおける エンコード済みフレーム
の操作を可能にする。
エンコーダーおよび デパケタイザーはそれぞれ、 空の キューに初期化される [[processedFramesQueue]] 内部スロットと、 エンコード済みフレーム frame が与えられたときに frame を返す [[transformFrameAlgorithm]] 内部スロットを持ち、そのスロットは パススルー アルゴリズムに初期化される。
エンコーダーがエンコード済みフレームを出力するたびに、ユーザー エージェントはそれに対して エンコーダー.[[transformFrameAlgorithm]] を呼び出し、 元のフレームの代わりに、その結果を関連する パケタイザーへ渡さなければならない。
デパケタイザーが エンコード済みフレームを出力するたびに、 ユーザーエージェントはそれに対して デパケタイザー.[[transformFrameAlgorithm]] を呼び出し、元のフレームの代わりに、その結果を関連する デコーダーへ渡さなければならない。
2.1. 拡張操作
各 RTCRtpTransceiver
の構築時に、
次の手順を実行する:
-
this.
[[useSFrame]]を undefined に初期化する。 -
this が メディア記述に関連付けられている場合、this.
[[useSFrame]]をそのメディア記述から初期化する。this.[[useSFrame]]が true である場合、this に対して SFrame RTP パケタイゼーションを有効にする。 -
そうでなければ、次の手順を実行するためにタスクをキューに入れる:
RTCRtpTransceiver.[[useSFrame]]
は、すでに SDP m-section に結び付けられている場合は同期的に、または
SDP m-section に関連付けられる前に非同期的に設定されるべきである。
これにより、RTCRtpTransceiver.[[useSFrame]]
と対応する SDP が常に同期されることが保証される。
このようにすることで、negotiation-needed フラグを確認するアルゴリズムのような、
negotiation-needed フラグに関連する処理は、RTCRtpTransceiver.[[useSFrame]]
を考慮する
必要がない。
各 RTCRtpSender
または RTCRtpReceiver
の構築時に、
次の手順を実行する:
-
this.
[[transform]]を null に初期化する。 -
this.
[[pipeToController]]を null に初期化する。 -
this.
[[frameSource]]を、this がRTCRtpSenderである場合は this の エンコーダーに、そうでなければ this の デパケタイザーに初期化する。
2.1.1. ストリーム処理
Streams のバックプレッシャーは、データパイプライン内で可能な限り早く データ生成を一時停止することで、処理とメモリ消費を制限しながらスループットを最適化できる。 これは、信頼性が不可欠であり、レイテンシーの懸念が比較的小さい文脈で有用である。 一方で、WebRTC メディアパイプラインは、たとえばさまざまな場所で フレームの破棄を許可し、回復メカニズムを使用することにより、 信頼性よりも低レイテンシーを重視する。 変換内でバッファリングを行うと、ウェブアプリケーションがあまり適応できないままレイテンシーが追加される。 とりわけ変換の両端を制御しているため、ユーザーエージェントがこれらの適応を行う責任を負う。 これらの理由により、WebRTC エンコード済み変換では Streams のバックプレッシャーは無効化される。
readEncodedData アルゴリズムは、RTCRtpScriptTransformer
transformer をパラメーターとして、frame を入力として与えられる。これは次の
手順を実行することにより定義される:
-
frame.
[[owner]]を transformer.[[frameSource]]に設定する。 -
frame.
[[counter]]を transformer.[[lastEnqueuedFrameCounter]]に設定する。 -
frame.
[[owner]]が デパケタイザーである場合:-
関連する RTP パケットが 絶対キャプチャ時刻用 RTP ヘッダー拡張を含む場合、 frame.
[[captureTime]]を absolute capture timestamp フィールドに設定し、存在するなら frame.[[senderCaptureTimeOffset]]を capture clock offset field に設定する。 -
そうでなく、関連する RTP パケットが 絶対キャプチャ時刻用 RTP ヘッダー拡張を含まないが、 以前の RTP パケットが含んでいた場合、 frame.
[[captureTime]]を timestamp interpolation に従って絶対キャプチャタイムスタンプを計算した結果に設定し、 frame.[[senderCaptureTimeOffset]]を存在していた直近の値に設定する。 -
そうでなければ、frame.
[[captureTime]]を undefined に設定し、 frame.[[senderCaptureTimeOffset]]を undefined に設定する。
-
-
frame.
[[owner]]が エンコーダーである場合、frame.[[captureTime]]を RTP Header Extension for Absolute Capture Time § absolute-capture-timestamp で説明されている方法論を用いた キャプチャタイムスタンプに設定し、 frame.[[senderCaptureTimeOffset]]を undefined に設定する。 -
frame を transformer.
[[readable]]にエンキューする。
writeEncodedData アルゴリズムは、RTCRtpScriptTransformer
transformer をパラメーターとして、frame を入力として与えられる。これは次の
手順を実行することにより定義される:
-
frame.
[[owner]]が transformer.[[frameSource]]と等しくない場合、 これらの手順を中止し、undefined で解決される promise を返す。プロセッサーは フレームを作成したり、ストリーム間でフレームを移動したりできない。 -
frame.
[[counter]]が transformer.[[lastReceivedFrameCounter]]以下である場合、これらの手順を中止し、 undefined で解決される promise を返す。プロセッサーは フレームを並べ替えることはできないが、遅延させたり破棄したりすることはできる。 -
transformer.
[[lastReceivedFrameCounter]]を frame.[[counter]]に設定する。 -
data を frame.
[[data]]とする。 -
serializedFrame を StructuredSerializeWithTransfer(frame, « data ») とする。
-
frameCopy を StructuredDeserializeWithTransfer(serializedFrame, frame の関連レルム) とする。
-
processedFrame を frameCopy の基盤となる エンコード済みフレームとする。
-
並列に、processedFrame を transformer.
[[frameSource]].[[processedFramesQueue]] にエンキューする。 -
undefined で解決される promise を返す。
送信側では、readEncodedData の一部として、
エンコーダーによって生成されたフレームは、エンキューされるとき、
transformer.[[readable]]
に、エンコーダーの出力順で入れられなければならない。
writeEncodedData は変換が
フレームを並べ替えられないことを保証するため、エンコーダーの出力順は、パケタイザーが RTP パケットを生成し、
RTP パケットシーケンス番号を割り当てる際に従う順序でもある。
パケタイザーは、
変換済みデータが、たとえば Annex B 開始コードで区切られた一連の NAL ユニットのように、
依然として元の形式に適合していることを期待するかもしれない。
受信側では、readEncodedData の一部として、
デパケタイザーによって生成されたフレームは、
同じ エンコーダーの出力順で、
transformer.[[readable]]
にエンキューされなければならない。
その順序が尊重されることを保証するため、デパケタイザーは通常、transformer.[[readable]]
にフレームをエンキューする前に、
必要に応じて RTP パケットシーケンス番号を使用して RTP パケットを並べ替える。
writeEncodedData は変換が
フレームを並べ替えられないことを保証するため、これは デコーダーが期待する順序となる。
2.1.2. RTCRtpTransform 共通処理
RTCRtpTransform には private スロットがある:
-
[[owner]]。型はRTCRtpSenderまたはRTCRtpReceiverであり、null に初期化される。
各 RTCRtpTransform は、関連付けアルゴリズム と 関連付け解除アルゴリズムを持ち、どちらも既定では空である。
2.2. 拡張属性
transform getter 手順は、
this.[[transform]] を返すものである。setter 手順は次のとおりである:
-
transform を setter への引数とする。
-
transceiver を、this に関連付けられた
RTCRtpTransceiverとする。 -
transform.
[[useSFrame]]が true である場合、次の手順を実行する:-
transceiver.
[[useSFrame]]が false である場合、InvalidModificationErrorを投げ、これらの手順を中止する。 -
そうでなく、transceiver.
[[useSFrame]]が undefined である場合、次の 手順を実行する:-
transceiver.
[[useSFrame]]を true に設定する。 -
transceiver に対して SFrame RTP パケタイゼーションを有効にする。
-
-
-
そうでなければ、次の手順を実行する:
-
transceiver.
[[useSFrame]]が true である場合、InvalidModificationErrorを投げ、これらの手順を中止する。 -
transceiver.
[[useSFrame]]を false に設定する。
-
-
transform が null ではなく、かつ transform.
[[owner]]が null ではない場合、InvalidStateErrorを投げ、これらの手順を中止する。 -
transform.
[[owner]]を this に設定する。 -
oldTransform を this.
[[transform]]とする。 -
oldTransform が null ではない場合、oldTransform の 関連付け解除 アルゴリズムを実行する。
-
this.
[[transform]]を transform に設定する。 -
transform が null ではない場合、transform の 関連付けアルゴリズムを this を伴って実行する。
-
transform が null である場合、次の手順を実行する:
-
frameSource を this.
[[frameSource]]とする。 -
並列に、frameSource.[[transformFrameAlgorithm]] を パススルーアルゴリズムに設定する。
-
このアルゴリズムは、変換を動的に更新できるように定義されている。 以前の変換から新しい変換への切り替えがどのフレームで発生するかについての保証はない。
ウェブアプリケーションが RTCRtpSender
の作成時に同期的に変換を設定する場合(たとえば addTrack の呼び出し時)、その変換は RTCRtpSender
の
エンコーダーによって生成された最初のフレームを受信する。
同様に、ウェブアプリケーションが RTCRtpReceiver
の作成時に同期的に変換を設定する場合(たとえば addTrack の呼び出し時、または track イベントハンドラーで)、その変換は RTCRtpReceiver
の
パケタイザーによって生成された最初の完全なフレームを受信する。
3. SFrame 変換
この節で提示される API により、アプリケーションは [RFC9605] で定義される特定の暗号スイートを用いて SFrame データを処理できる。
// List of supported cipher suites, as defined in [[RFC9605]] section 4.5 and in https://datatracker.ietf.org/doc/draft-barnes-sframe-iana-256/.enum {SFrameCipherSuite ,"AES_128_CTR_HMAC_SHA256_80" ,"AES_128_CTR_HMAC_SHA256_64" ,"AES_128_CTR_HMAC_SHA256_32" ,"AES_128_GCM_SHA256_128" ,"AES_256_GCM_SHA512_128" ,"AES_256_CTR_HMAC_SHA512_80" ,"AES_256_CTR_HMAC_SHA512_64" };"AES_256_CTR_HMAC_SHA512_32" dictionary {SFrameTransformOptions required SFrameCipherSuite ; };cipherSuite enum {SFrameType ,"per-frame" };"per-packet" dictionary :RTCRtpSFrameEncrypterOptions SFrameTransformOptions {SFrameType = "per-frame"; };type typedef [EnforceRange ]unsigned long long ;SmallCryptoKeyID typedef (SmallCryptoKeyID or bigint );CryptoKeyID interface mixin {SFrameEncrypterManager Promise <undefined >setEncryptionKey (CryptoKey ,key CryptoKeyID ); };keyId interface mixin {SFrameDecrypterManager Promise <undefined >addDecryptionKey (CryptoKey ,key CryptoKeyID );keyId Promise <undefined >removeDecryptionKey (CryptoKeyID );keyId attribute EventHandler ; }; [onerror Exposed =Window ]interface {RTCRtpSFrameEncrypter constructor (RTCRtpSFrameEncrypterOptions ); };options RTCRtpSFrameEncrypter includes SFrameEncrypterManager ; [Exposed =Window ]interface :RTCRtpSFrameDecrypter EventTarget {constructor (SFrameTransformOptions ); };options RTCRtpSFrameDecrypter includes SFrameDecrypterManager ; [Exposed =(Window ,DedicatedWorker )]interface {SFrameEncrypterStream constructor (SFrameTransformOptions ); };options SFrameEncrypterStream includes GenericTransformStream ;SFrameEncrypterStream includes SFrameEncrypterManager ; [Exposed =(Window ,DedicatedWorker )]interface :SFrameDecrypterStream EventTarget {constructor (SFrameTransformOptions ); };options SFrameDecrypterStream includes GenericTransformStream ;SFrameDecrypterStream includes SFrameDecrypterManager ;enum {SFrameTransformErrorEventType ,"authentication" ,"keyID" }; ["syntax" Exposed =(Window ,DedicatedWorker )]interface :SFrameTransformErrorEvent Event {(constructor DOMString ,type SFrameTransformErrorEventInit );eventInitDict readonly attribute SFrameTransformErrorEventType ;errorType readonly attribute CryptoKeyID ?;keyID readonly attribute any ; };frame dictionary :SFrameTransformErrorEventInit EventInit {required SFrameTransformErrorEventType ;errorType required any ;frame CryptoKeyID ?; };keyID
new RTCRtpSFrameEncrypter(options)
コンストラクターの手順は、次のとおり:
-
options をメソッドの第 1 引数とする。
-
SFrame 初期化アルゴリズムを this と options で実行する。
-
this.
[[role]]を 'encrypt' に設定する。 -
this.
[[useSFrame]]を true に設定する。
new RTCRtpSFrameDecrypter(options)
コンストラクターの手順は、次のとおり:
-
options をメソッドの第 1 引数とする。
-
SFrame 初期化アルゴリズムを this と options で実行する。
-
this.
[[role]]を 'decrypt' に設定する。 -
this.
[[useSFrame]]を true に設定する。
new SFrameEncrypterStream(options)
コンストラクターの手順は、次のとおり:
-
options をメソッドの第 1 引数とする。
-
SFrame 初期化アルゴリズムを this と options で実行する。
-
this.
[[role]]を 'encrypt' に設定する。
new SFrameDecrypterStream(options)
コンストラクターの手順は、次のとおり:
-
options をメソッドの第 1 引数とする。
-
SFrame 初期化アルゴリズムを this と options で実行する。
-
this.
[[role]]を 'decrypt' に設定する。
3.1. アルゴリズム
this および options が与えられる SFrame 初期化アルゴリズムは、次の手順を実行する:
-
transformAlgorithm を、frame を入力として取り、 this と frame で SFrame 変換アルゴリズムを実行するアルゴリズムとする。
-
options["
type"] が存在する場合、これらの手順を実行する:-
options["
type"] が 'per-frame' であれば、[RTP-SFRAME-PAYLOAD] で定義される per-frame 送信を使用する。 -
そうでなければ、[RTP-SFRAME-PAYLOAD] で定義される per-packet 送信を使用する。
-
-
this.
[[transform]]を新しいTransformStreamに設定する。 -
設定 this.
[[transform]]を、transformAlgorithm を transformAlgorithm に設定して行う。 -
this.
[[cipherSuite]]を options["cipherSuite"] に設定する。 -
this.
[[readable]]を this.[[transform]].[[readable]]に設定する。 -
this.
[[writable]]を this.[[transform]].[[writable]]に設定する。
this および frame が与えられる SFrame 変換アルゴリズムは、次の手順を実行する:
-
role を this.
[[role]]とする。 -
this.
[[owner]]がRTCRtpSenderである場合、role を 'encrypt' に設定する。 -
this.
[[owner]]がRTCRtpReceiverである場合、role を 'decrypt' に設定する。 -
data を undefined とする。
-
frame が
BufferSourceである場合、data を frame に設定する。 -
frame が
RTCEncodedAudioFrameである場合、data を frame.dataに設定する。 -
frame が
RTCEncodedVideoFrameである場合、data を frame.dataに設定する。 -
data が undefined である場合、これらの手順を中止する。
-
buffer を、data、this.
[[cipherSuite]]、 および role をパラメーターとして SFrame アルゴリズムを実行した結果とする。 このアルゴリズムは [RFC9605] によって定義され、ArrayBufferを返す。 -
SFrame アルゴリズムがエラーを伴って突然終了した場合、次のサブ手順を実行するために タスクをキューに入れる:
-
復号側で、data が SFrame 形式に従っていないことにより処理が失敗した場合、 this に対して
errorという名前のイベントを発火する。 その際、SFrameTransformErrorEventインターフェイスを用い、そのerrorType属性をsyntaxに設定し、そのframe属性を frame に設定する。 -
復号側で、data から解析された鍵識別子が不明であることにより 処理が失敗した場合、this に対して
errorという名前のイベントを発火する。 その際、SFrameTransformErrorEventインターフェイスを用い、そのerrorType属性をkeyIDに設定し、そのframe属性を frame に設定し、そのkeyID属性を SFrame ヘッダー内で解析された keyID 値に設定する。 -
復号側で、認証タグの検証により処理が失敗した場合、this に対して
errorという名前のイベントを発火する。 その際、SFrameTransformErrorEventインターフェイスを用い、そのerrorType属性をauthenticationに設定し、そのframe属性を frame に設定する。 -
これらの手順を中止する。
-
-
frame が
BufferSourceである場合、frame を buffer に設定する。 -
frame が
RTCEncodedAudioFrameである場合、frame.dataを buffer に設定する。 -
frame が
RTCEncodedVideoFrameである場合、frame.dataを buffer に設定する。 -
frame を this.
[[transform]]にエンキューする。
3.2. メソッド
setEncryptionKey(key, keyId)
メソッド手順は次のとおりである:
-
promise を新しい promise とする。
-
keyId が、0 以上 264-1 以下の整数として表現できない
bigintである場合、promise をRangeError例外で却下し、これらの手順を中止する。 -
並列に、次の手順を実行する:
-
[RFC9605] によって定義されるように、SFrame 変換暗号化アルゴリズムの鍵材料を key および keyId に設定する。
-
鍵材料の設定が失敗した場合、promise を
InvalidModificationError例外で却下するように タスクをキューに入れ、これらの手順を中止する。 -
promise を undefined で解決するように タスクをキューに入れる。
-
-
promise を返す。
addDecryptionKey(key, keyId)
メソッド手順は次のとおりである:
-
promise を新しい promise とする。
-
keyId が、0 以上 264-1 以下の整数として表現できない
bigintである場合、promise をRangeError例外で却下し、これらの手順を中止する。 -
並列に、次の手順を実行する:
-
keyStore を、[RFC9605] によって定義される、SFrame 変換アルゴリズムに使用される鍵ストアとする。
-
keyStore[keyId] を key に 設定する。
-
鍵材料の設定が失敗した場合、promise を
InvalidModificationError例外で却下するように タスクをキューに入れ、これらの手順を中止する。 -
promise を undefined で解決するように タスクをキューに入れる。
-
-
promise を返す。
removeDecryptionKey(keyId)
メソッド手順は次のとおりである:
-
promise を新しい promise とする。
-
keyId が、0 以上 264-1 以下の整数として表現できない
bigintである場合、promise をRangeError例外で却下し、これらの手順を中止する。 -
並列に、次の手順を実行する:
-
keyStore を、[RFC9605] によって定義される、SFrame 変換アルゴリズムに使用される鍵ストアとする。
-
keyStore[keyId] を削除する。
-
promise を undefined で解決するように タスクをキューに入れる。
-
-
promise を返す。
4. スクリプト変換
この節において、キャプチャシステムとはメディアの供給元となるシステムを指し、送信側システムとは、
RTCEncodedFrameMetadata
データが入力される受信側システムへ RTP および RTCP パケットを送信するシステムを指す。
4.1. RTCEncodedFrameMetadata 辞書
dictionary RTCEncodedFrameMetadata {unsigned long synchronizationSource ;octet payloadType ;sequence <unsigned long >contributingSources ;unsigned long rtpTimestamp ;DOMHighResTimeStamp receiveTime ;DOMHighResTimeStamp captureTime ;DOMHighResTimeStamp senderCaptureTimeOffset ;DOMString mimeType ; };
4.1.1. メンバー
-
synchronizationSource, 型 unsigned longunsigned long -
synchronization source (ssrc) 識別子は、[RFC3550] に従う符号なし整数値であり、エンコード済みフレームオブジェクトが記述している RTP パケットのストリームを識別するために使用される。
-
payloadType, 型 octetoctet -
ペイロード型は、[RFC3550] に従う 0 から 127 までの範囲の符号なし整数値であり、 RTP ペイロードの形式を記述するために使用される。
-
contributingSources, 型sequence<unsigned long>sequence<unsigned long> -
[RFC3550] で定義される contribution source のリスト(csrc list)。
-
rtpTimestamp, 型 unsigned longunsigned long -
RTP タイムスタンプ識別子は、[RFC3550] に従う符号なし整数値であり、RTP データパケット内の最初のオクテットのサンプリング時点を反映する。
-
receiveTime, 型 DOMHighResTimeStampDOMHighResTimeStamp -
RTCRtpReceiver から来るフレームについて、このメディアフレームを生成するために使用された 最後に受信されたパケットのタイムスタンプを表す。この タイムスタンプは、
Performance.timeOriginに相対的である。 -
captureTime, 型 DOMHighResTimeStampDOMHighResTimeStamp -
このフレームのキャプチャシステムのクロックにおけるキャプチャ時刻。 このメンバーを入力する際、ユーザーエージェントはフレームの
[[captureTime]]スロットの値を返さなければならず、 それはPerformance.timeOriginに相対的になるようにシフトされる。 -
senderCaptureTimeOffset, 型 DOMHighResTimeStampDOMHighResTimeStamp -
senderCaptureTimeOffsetは、同じフレームについて、送信側システム自身の NTP クロックとキャプチャシステムの NTP クロックとの間の オフセットに関する送信側システムの推定値であり、captureTimeの由来となったものと同じフレームに対するものである。 このメンバーを入力する際、ユーザーエージェントはフレームの[[senderCaptureTimeOffset]]スロットの値を返さなければならない。 -
mimeType, 型 DOMStringDOMString -
IANA メディア型レジストリ [IANA-MEDIA-TYPES] で定義されるコーデック MIME メディア型/サブ型。 例: audio/opus または video/VP8。
4.2.
RTCEncodedVideoFrameMetadata
辞書
dictionary RTCEncodedVideoFrameMetadata :RTCEncodedFrameMetadata {unsigned long long frameId ;sequence <unsigned long long >dependencies ;unsigned short ;width unsigned short ;height unsigned long ;spatialIndex unsigned long ;temporalIndex long long timestamp ; // microseconds };
4.2.1. メンバー
-
frameId, 型 unsigned long longunsigned long long -
エンコード済みフレームの識別子であり、復号順に単調増加する。その下位 16 ビットは、存在する場合、[AV1-RTP-SPEC] の Appendix A で定義される AV1 Dependency Descriptor Header Extension の frame_number と一致する。 受信フレームについては、Dependency Descriptor Header Extension が存在する場合にのみ存在する。
-
dependencies, 型sequence<unsigned long long>sequence<unsigned long long> -
このフレームが参照するフレームの frameId のリスト。 [AV1-RTP-SPEC] の Appendix A で定義される AV1 Dependency Descriptor Header Extension が存在する場合にのみ、受信フレームについて存在する。
-
timestamp, 型 long longlong long -
生フレームのメディア提示タイムスタンプ(PTS)をマイクロ秒単位で表し、 このフレームに対応する生フレームの
timestampと一致する。
4.3.
RTCEncodedVideoFrame インターフェイス
dictionary {RTCEncodedVideoFrameOptions RTCEncodedVideoFrameMetadata ; }; // New interfaces to define RTC specific encoded video and audio frames used by RTCRtpScriptTransform. [metadata Exposed =(Window ,DedicatedWorker ),Serializable ]interface RTCEncodedVideoFrame {(constructor RTCEncodedVideoFrame ,originalFrame optional RTCEncodedVideoFrameOptions = {});options readonly attribute EncodedVideoChunkType type ;attribute ArrayBuffer data ;RTCEncodedVideoFrameMetadata getMetadata (); };
4.3.1. コンストラクター
-
constructor() -
指定された originalFrame および options.
[metadata]から、新しいRTCEncodedVideoFrameを作成する。新しく作成されたフレームは originalFrame から完全に独立しており、その[[data]]は originalFrame.[[data]]の深いコピーである。 新しいフレームの[[metadata]]は originalFrame.[[metadata]]の深いコピーであり、 フィールドは options.[metadata]に存在するフィールドの深いコピーで 置き換えられる。呼び出されたとき、次の手順を実行する:
-
this.
[[type]]を originalFrame.[[type]]に設定する。 -
this.
[[data]]を、[CloneArrayBuffer](originalFrame.[[data]], 0, originalFrame.[[data]].[[ArrayBufferByteLength]]) の結果とする。 -
[[metadata]]を、この新しく構築された フレームに関連付けられたメタデータを表すものとする。-
originalFrame.
[[getMetadata()]]の 各 {[[key]],[[value]]} ペアについて、[[metadata]].[[key]]を[[value]]の深いコピーに設定する。 -
options.
[metadata]の 各 {[[key]],[[value]]} ペアについて、[[metadata]].[[key]]を[[value]]の深いコピーに設定する。
-
-
4.3.2. メンバー
-
type, 型 EncodedVideoChunkType, readonlyEncodedVideoChunkType -
type 属性により、アプリケーションはフレームがキーフレームであるかデルタフレームであるかを判定できる。 取得時には、this.
[[type]]が返されなければならない。 -
data, 型 ArrayBufferArrayBuffer -
エンコード済みフレームデータ。データの形式は、フレームのエンコード/デコードに 使用される動画コーデックに依存し、これは
mimeTypeを見ることで判定できる。 SVC については、各空間レイヤーが 個別に変換される。 取得時には、this.[[data]]が返されなければならない。設定時には、 this.[[data]]が新しい値に設定されなければならない。パケタイザーは特定の要素、たとえば AV1 temporal delimiter OBU を破棄する可能性があるため、 受信側変換への入力は、送信側変換の出力と異なる場合がある。
次の表にいくつかの例を示す:
mimeType データ形式 video/VP8 データは、 9.1 節で定義される "uncompressed data chunk" で始まり、 その後に残りのフレームデータが続く。 VP8 payload descriptor にはアクセスできない。 video/VP9 データは、[VP9] の Section 6 で説明されるフレームである。 VP9 payload descriptor にはアクセスできない。 video/H264 データは、[ITU-T-REC-H.264] Annex B で定義される Annex B 形式の NAL ユニット列である。 video/AV1 データは、[AV1] の Section 5 で説明される low-overhead bitstream format に適合する一連の OBU である。 AV1 aggregation header にはアクセスできない。
4.3.3. メソッド
-
getMetadata() -
フレームに関連付けられたメタデータを返す。
4.3.4. 直列化
RTCEncodedVideoFrame
オブジェクトは直列化可能オブジェクトである。
それらの直列化手順は、value、serialized、
および forStorage が与えられ、次のとおりである:
-
forStorage が true である場合、
DataCloneErrorを投げる。 -
serialized.
[[type]]を value.[[type]]の値に設定する。 -
serialized.
[[metadata]]を value のメタデータの内部表現に設定する。 -
serialized.
[[data]]を value.[[data]]の 下位直列化に設定する。
それらの逆直列化手順は、serialized、 value および realm が与えられ、次のとおりである:
-
value.
[[type]]を serialized.[[type]]に設定する。 -
value のメタデータを serialized.
[[metadata]]のプラットフォームオブジェクト表現に設定する。 -
value.
[[data]]を serialized.[[data]]の下位逆直列化に設定する。
直列化された RTCEncodedVideoFrame の内部形式は観察できない。
これは主に、writeEncodedData アルゴリズム内のフレーム複製、および
structuredClone()
操作で使用できるように定義されている。
したがって、実装は最適に機能する任意の方法を自由に選択できる。
4.4.
RTCEncodedAudioFrameMetadata
辞書
dictionary RTCEncodedAudioFrameMetadata :RTCEncodedFrameMetadata {short sequenceNumber ;double audioLevel ; };
4.4.1. メンバー
-
sequenceNumber, 型 shortshort -
[RFC3550] で定義される RTP シーケンス番号。着信音声フレームにのみ存在する。
2 つのシーケンス番号を比較するには、[RFC1982] で説明されるシリアル番号演算が必要である。
-
audioLevel, 型 doubledouble -
このフレームの音声レベル。値は 0..1(線形)の範囲であり、 1.0 は 0 dBov、0 は無音、0.5 は 0 dBov からの音圧レベルにおける およそ 6 dBSPL の変化を表す。
フレームがリモート由来のトラックから来る場合、これは [RFC6464] で定義されるレベル値から変換されなければならない。 フレームの受信済みパケット内に [RFC6464] ヘッダー拡張が存在しない場合、 この値は存在してはならない。 この RFC は音声レベルを 0 から 127 までの整数値として定義し、 システムが符号化可能な最も大きい信号を基準とした負のデシベル単位の 音声レベルを表す。したがって、0 はシステムが符号化可能な最も大きい信号を表し、 127 は無音を表す。これらの値を線形の 0..1 範囲に変換するには、値 127 を 0 に変換し、その他のすべての値は 次の式を用いて変換される:
10^(-rfc_level/20)。フレームがローカル由来のトラックから来る場合、レベルはソースから 直接取得されなければならず、ネゴシエートされている場合は [RFC6464] ヘッダー拡張用の値を生成する入力として使用されなければならない。
4.5.
RTCEncodedAudioFrame インターフェイス
dictionary {RTCEncodedAudioFrameOptions RTCEncodedAudioFrameMetadata ; }; [metadata Exposed =(Window ,DedicatedWorker ),Serializable ]interface RTCEncodedAudioFrame {(constructor RTCEncodedAudioFrame ,originalFrame optional RTCEncodedAudioFrameOptions = {});options attribute ArrayBuffer data ;RTCEncodedAudioFrameMetadata getMetadata (); };
4.5.1. コンストラクター
-
constructor() -
指定された originalFrame および options.
[metadata]から、新しいRTCEncodedAudioFrameを作成する。新しく作成されたフレームは originalFrame から完全に独立しており、その[[data]]は originalFrame.[[data]]の深いコピーである。 新しいフレームの[[metadata]]は originalFrame.[[metadata]]の深いコピーであり、 フィールドは options.[metadata]に存在するフィールドの深いコピーで 置き換えられる。呼び出されたとき、次の手順を実行する:
-
this.
[[data]]を、[CloneArrayBuffer](originalFrame.[[data]], 0, originalFrame.[[data]].[[ArrayBufferByteLength]]) の結果とする。 -
[[metadata]]を、この新しく構築された フレームに関連付けられたメタデータを表すものとする。-
originalFrame.
[[getMetadata()]]の 各 {[[key]],[[value]]} ペアについて、[[metadata]].[[key]]を[[value]]の深いコピーに設定する。 -
options.
[metadata]の 各 {[[key]],[[value]]} ペアについて、[[metadata]].[[key]]を[[value]]の深いコピーに設定する。
-
-
4.5.2. メンバー
-
data, 型 ArrayBufferArrayBuffer -
エンコード済みフレームデータ。データの形式は、フレームのエンコード/デコードに 使用される音声コーデックに依存し、これは
mimeTypeを見ることで判定できる。 取得時には、this.[[data]]が返されなければならない。設定時には、 this.[[data]]が新しい値に設定されなければならない。 次の表にいくつかの例を示す:mimeType データ形式 audio/opus データは、 3 節で説明される Opus パケットである。[RFC6716]。 audio/PCMU データは任意長のバイト列であり、各バイトは [ITU-G.711] の Table 2a および 2b で定義される u-law 符号化 PCM サンプルである。 audio/PCMA データは任意長のバイト列であり、各バイトは [ITU-G.711] の Tables 1a および 1b で定義される A-law 符号化 PCM サンプルである。 audio/G722 データは [ITU-G.722] で説明される G.722 音声である。 audio/RED データは、 3 節で説明される Redundant Audio Data である。[RFC2198]。 audio/CN データは、 3 節で説明される Comfort Noise である。[RFC3389]。
4.5.3. メソッド
-
getMetadata() -
フレームに関連付けられたメタデータを返す。
4.5.4. 直列化
RTCEncodedAudioFrame
オブジェクトは直列化可能オブジェクトである。
それらの直列化手順は、value、
serialized、および forStorage が与えられ、次のとおりである:
-
forStorage が true である場合、
DataCloneErrorを投げる。 -
serialized.
[[metadata]]を value のメタデータの内部表現に設定する。 -
serialized.
[[data]]を value.[[data]]の 下位直列化に設定する。
それらの逆直列化手順は、serialized、 value および realm が与えられ、次のとおりである:
-
value のメタデータを serialized.
[[metadata]]のプラットフォームオブジェクト表現に設定する -
value.
[[data]]を serialized.[[data]]の下位逆直列化に設定する。
5.
RTCRtpScriptTransform インターフェイス
enum {RTCRtpScriptTransformType };"sframe" dictionary {WorkerAndParameters required Worker ;worker RTCRtpScriptTransformType ; };type typedef (Worker or WorkerAndParameters ); [WorkerOrWorkerAndParameters Exposed =Window ]interface RTCRtpScriptTransform {constructor (WorkerOrWorkerAndParameters ,workerOrWorkerAndParameters optional any ,options optional sequence <object >); };transfer
5.1. 内部スロット
RTCRtpScriptTransform
オブジェクトは次の内部スロットを持つ:
| 内部スロット | 説明(非規範的) |
|---|---|
[[worker]]
| コンストラクターで提供された Worker。
|
5.2. コンストラクター
new RTCRtpScriptTransform(workerOrWorkerAndParameters, options, transfer)
コンストラクター手順は次のとおりである:
-
worker を undefined とする。
-
useSFrame を undefined とする。
-
workerOrWorkerAndParameters が
Workerオブジェクトである場合、worker を workerOrWorkerAndParameters に設定し、 useSFrame を false に設定する。 -
そうでなければ、次のサブ手順を実行する:
-
worker を workerOrWorkerAndParameters["worker"] に設定する。
-
workerOrWorkerAndParameters["type"] が "sframe" である場合は useSFrame を true に、そうでなければ false に設定する。
-
-
this の内部スロットを次のように初期化する:
[[worker]]-
worker
-
this.
[[useSFrame]]を useSFrame に初期化する。 -
serializedOptions を StructuredSerializeWithTransfer(options, transfer) の結果とする。
-
worker の
WorkerGlobalScopeで、DOM 操作タスクソース上にグローバルタスクをキューに入れ、 次の手順を実行する:-
transformerOptions を StructuredDeserializeWithTransfer(serializedOptions, 現在の Realm) の結果とする。
-
transformer を、transformerOptions を用いて
RTCRtpScriptTransformerを作成する結果とする。 -
transformer の関連グローバルオブジェクト上で、
RTCTransformEventを用い、そのtransformerを transformer に設定して、rtctransformという名前のイベントを発火する。
-
// FIXME: エラー処理を記述する(RTCRtpScriptTransform 作成時に worker closing flag が true である場合。 および transform がデータを処理している間に worker が終了される場合)。
5.3. アルゴリズム
各 RTCRtpScriptTransform
は、rtcObject が与えられる次の関連付けアルゴリズムを持つ:
-
transform を、関連付けアルゴリズム を所有する
RTCRtpScriptTransformオブジェクトとする。 -
frameSource を rtcObject の
[[frameSource]]とする。 -
workerGlobalScope を transform.
[[worker]]のWorkerGlobalScopeとする。 -
workerGlobalScope で、DOM 操作タスクソース上にグローバルタスクをキューに入れ、 次の手順を実行する:
-
transformer を、transform に関連付けられた
RTCRtpScriptTransformerオブジェクトとする。 -
transformer.
[[frameSource]]を frameSource に設定する。
-
-
並列に、frameSource.[[transformFrameAlgorithm]] を、入力として エンコード済み フレーム frame が与えられる次の手順に設定する:
-
workerGlobalScope で、DOM 操作タスクソース上にグローバルタスクをキューに入れ、 次の手順を実行する:
-
transformer を、transform に関連付けられた
RTCRtpScriptTransformerオブジェクトとする。 -
frame が動画フレームである場合は frame から新しい
RTCEncodedVideoFrameを作成し、そうでなければ frame から新しいRTCEncodedAudioFrameを作成し、それを jsFrame とする。 -
transformer および jsFrame を用いて readEncodedData を呼び出す。
-
-
frameSource.[[processedFramesQueue]] が空でなくなるまで待機する。
-
frameSource.[[processedFramesQueue]] からデキューした結果を返す。
-
各 RTCRtpScriptTransform
は、次の関連付け解除アルゴリズムを持つ:
-
transform を、関連付け解除 アルゴリズムを所有する
RTCRtpScriptTransformオブジェクトとする。 -
transform.
[[worker]]のWorkerGlobalScopeで、DOM 操作タスクソース上にグローバルタスクをキューに入れ、 次の手順を実行する:-
transformer を、transform に関連付けられた
RTCRtpScriptTransformerオブジェクトとする。 -
transformer.
[[readable]]をキャンセルする。 -
transformer.
[[writable]]を中止する。
-
6.
RTCRtpScriptTransformer インターフェイス
[Exposed =DedicatedWorker ]interface RTCRtpScriptTransformer :EventTarget { // Attributes and methods related to the transformer sourcereadonly attribute ReadableStream readable ;Promise <undefined >generateKeyFrame (optional DOMString );rid Promise <undefined >sendKeyFrameRequest (); // Attributes and methods related to the transformer sinkreadonly attribute WritableStream writable ;attribute EventHandler onkeyframerequest ; // Attributes for configuring the Javascript codereadonly attribute any options ; };
6.1. 内部スロット
RTCRtpScriptTransformer
オブジェクトは次の内部スロットを持つ:
| 内部スロット | 説明(非規範的) |
|---|---|
[[frameSource]]
| エンコーダー、デパケタイザー、または undefined。 |
[[options]]
| 省略可能な Object、
または null。
|
[[readable]]
| ReadableStream。
|
[[writable]]
| WritableStream。
|
[[lastReceivedFrameCounter]]
| 受信されたフレーム数。 |
[[lastEnqueuedFrameCounter]]
| エンキューされたフレーム数。 |
RTCRtpScriptTransformer
を作成するには、
次の手順を実行する:
-
transformer を、次を伴う新しい
RTCRtpScriptTransformerとする:[[frameSource]]-
undefined
[[options]]-
options
[[readable]]-
新しい
ReadableStream [[writable]]-
新しい
WritableStream [[lastReceivedFrameCounter]]-
0
[[lastEnqueuedFrameCounter]]-
0
-
transformer.
[[readable]]を設定する。this をパラメーターとして与えられる readEncodedData アルゴリズムは、 エンコード済みフレームをそれに提供する。
-
writeAlgorithm を、frame が与えられたときに、 this をパラメーターとして、frame を入力として writeEncodedData を実行する動作とする。
-
transformer.
[[writable]]を設定し、 その writeAlgorithm を writeAlgorithm に設定し、その highWaterMark をInfinityに設定する。highWaterMark は、バックプレッシャーを明示的に無効化するために Infinity に設定される。
-
transformer を返す。
6.2. メソッド
generateKeyFrame(rid)
メソッド手順は次のとおりである:
-
promise を新しい promise とする。
-
promise、this.
[[frameSource]]および rid を用いて キーフレーム生成アルゴリズムを実行する。 -
promise を返す。
sendKeyFrameRequest() メソッド
手順は次のとおりである:
-
promise を新しい promise とする。
-
promise および this.
[[frameSource]]を用いて キーフレーム要求送信 アルゴリズムを実行する。 -
promise を返す。
6.3. 属性
options getter 手順は次のとおりである:
-
this.
[[options]]を返す。
readable getter 手順は次のとおりである:
-
this.
[[readable]]を返す。
writable getter 手順は次のとおりである:
-
this.
[[writable]]を返す。
onbandwidthestimate
EventHandler は bandwidthestimate 型を持つ。
onkeyframerequest
EventHandler は keyframerequest 型を持つ。
6.4. イベント
[Exposed =DedicatedWorker ]interface :RTCTransformEvent Event {readonly attribute RTCRtpScriptTransformer ; };transformer partial interface DedicatedWorkerGlobalScope {attribute EventHandler ; }; [onrtctransform Exposed =DedicatedWorker ]interface :KeyFrameRequestEvent Event {(constructor DOMString ,type optional DOMString );rid readonly attribute DOMString ?; };rid
次のイベントは RTCRtpScriptTransformer
上で発火する:
-
KeyFrameRequestEvent型の keyframerequest - シンクがキーフレームが要求されたと判定したときに発火する。
KeyFrameRequestEvent
型のイベントを生成する手順は次のとおりである:
関連付けられた RTCRtpScriptTransformer
transformer のエンコーダーが、
たとえば着信 RTCP Picture Loss
Indication (PLI) または Full Intra Refresh (FIR) からキーフレーム要求を受信したとき、
次の手順を実行するためにタスクをキューに入れる:
-
rid を適切なレイヤーの RID に設定する、または要求が特定のレイヤーに対するものではない場合は undefined に設定する。
-
transformer に対して
keyframerequestという名前のイベントを発火する。 その際、KeyFrameRequestEventを用い、そのcancelable属性を "true" に初期化し、ridを rid に設定する。 -
イベントのキャンセル済みフラグが true である場合、これらの手順を中止する。
-
新しい promise、transformer.
[[frameSource]]および rid を用いて キーフレーム生成アルゴリズムを実行する。
6.5. キーフレームアルゴリズム
promise、frameSource および rid が与えられる キーフレーム生成アルゴリズムは、次の手順を実行することにより定義される:
-
frameSource がエンコーダーでない場合、promise を
InvalidStateErrorで却下し、 これらの手順を中止する。 -
encoder を frameSource とする。
-
encoder が動画
RTCRtpSenderに属していない場合、promise をInvalidStateErrorで却下し、 これらの手順を中止する。 -
rid が定義されているが、[RFC8851] の Section 10 で指定される文法要件に適合しない場合、 promise を
TypeErrorで却下し、 これらの手順を中止する。 -
並列に、次の手順を実行する:
-
layers を、この encoder に対するレイヤーの新しいリストとし、 negotiated encoding index の順に並べる。
-
layers から、
activeでないすべてのレイヤー、または対応するRTCRtpSendertrack が終了しているすべてのレイヤーを削除する。 -
rid が undefined でない場合、layers から、RID が rid でない すべてのレイヤーを削除する。
注: rid が渡されない場合、 すべてのアクティブなレイヤーについてキーフレームが生成される。
-
layers がここで空である場合、promise を
NotFoundErrorで却下し、これらの手順を中止するためにタスクをキューに入れる。 -
layers から、 encoder.
[[pendingKeyFrameTasks]]内の任意のタスクの任意の[[layers]]内にすでに見つかっているすべてのレイヤーを削除する。 -
task と呼ばれる pending key frame task を作成し、 task.
[[layers]]を layers に設定し、 task.[[promise]]を promise に設定する。 -
encoder.
[[pendingKeyFrameTasks]]が undefined である場合、 encoder.[[pendingKeyFrameTasks]]を空の集合に初期化する。 -
task を encoder.
[[pendingKeyFrameTasks]]に追加する。 -
layers 内の各 layer について(もしあれば)、 encoder に、その layer へ次に提供される動画フレームに対する キーフレームを生成するよう指示する。
-
RTCRtpScriptTransformer
transformer に関連付けられた任意のエンコーダーについて、
ユーザーエージェントは、任意の frame が transformer.[[readable]]
にエンキューされる直前に、次の手順を実行しなければならない:
-
encoder を transformer.
[[frameSource]]とする。 -
encoder.
[[pendingKeyFrameTasks]]が undefined である場合、これらの手順を中止する。 -
frame が動画
"key"フレームでない場合、これらの手順を中止する。 -
encoder.
[[pendingKeyFrameTasks]]内の各 task について、次の手順を実行する:
対応するキーフレームを RTCRtpScriptTransformer
の
readable にエンキューする直前に promise を解決することで、
promise の解決コールバックは、対応するキーフレームが公開される直前に常に実行される。
promise が複数のレイヤーに関連付けられている場合、それらすべてについてキーフレームがエンキューされた時点で解決される。
promise および frameSource が与えられる キーフレーム要求送信アルゴリズムは、 次の手順を実行することにより定義される:
-
frameSource がデパケタイザーでない場合、promise を
InvalidStateErrorで却下し、 これらの手順を中止する。 -
depacketizer を frameSource とする。
-
depacketizer が動画
RTCRtpReceiverに属していない場合、promise をInvalidStateErrorで却下し、 これらの手順を中止する。 -
並列に、次の手順を実行する:
-
depacketizer の receiver による Full Intra Request (FIR) の送信が適切と見なされない場合、 promise を undefined で解決し、これらの手順を中止する。 [RFC5104] の Section 4.3.1 は、Full Intra Request の送信がいつどのように適切であるかの指針を提供する。
-
[RFC5104] の section 4.3.1 で定義される Full Intra Request (FIR) パケットを生成し、 depacketizer の receiver を通じて送信する。
-
promise を undefined で解決 するためにタスクをキューに入れる。
-
7. プライバシーとセキュリティに関する考慮事項
この API は、JavaScript にメディアストリームの内容へのアクセスを与える。これは Canvas や WebAudio など、他のソースからも利用可能である。
しかし、分離されているストリーム([WEBRTC-IDENTITY] で指定されるもの)または他のオリジンによって汚染されたストリームは、 この API を用いてアクセスできない。これは分離規則を破ることになるためである。
この API は、それ以外では利用できないタイミング情報のいくつかの側面へのアクセスを可能にし、 それによってフィンガープリンティング面が生じる。
この API はエンコード済みメディアへのアクセスを与える。つまり、JS アプリケーションは、 パケタイザーやデコーダーのような内部コンポーネントへ渡されるものを完全に制御できる。 これには、これらのコンポーネント内でデータがどのように扱われるかの監査に、 追加の注意が必要となる場合がある。
たとえば、パケタイザーは信頼されたエンコーダーからのデータのみを見ることを期待している場合があり、 信頼されていないソースからのデータ受信について監査されていない場合がある。
8. 例
解説 文書を参照。