メディアソース拡張™

W3C作業草案

この文書の詳細情報
このバージョン:
https://www.w3.org/TR/2025/WD-media-source-2-20250821/
最新公開バージョン:
https://www.w3.org/TR/media-source-2/
最新エディタドラフト:
https://w3c.github.io/media-source/
履歴:
https://www.w3.org/standards/history/media-source-2/
コミット履歴
最新の勧告:
https://www.w3.org/TR/2016/REC-media-source-20161117/
編集者:
(Apple Inc.)
Mark Watson (Netflix Inc.)
以前の編集者:
(W3C招聘エキスパート) -
Jerry Smith (Microsoft Corporation) -
Aaron Colwell (Google Inc.) -
Adrian Bateman (Microsoft Corporation) -
フィードバック:
GitHub w3c/media-source (プルリクエスト, 新しい課題, 公開中の課題)
public-media-wg@w3.org 件名 [media-source-2] … メッセージトピック … (アーカイブ)
ブラウザ対応状況:
caniuse.com

概要

この仕様は、HTMLMediaElement [HTML] を拡張し、 JavaScriptによるメディアストリームの生成と再生を可能にします。JavaScriptでストリームを生成できることで、アダプティブストリーミングやライブストリームのタイムシフトなど、さまざまなユースケースに対応できます。

この文書のステータス

このセクションは、公開時点での本 文書のステータスを説明します。現在のW3C 公開文書や、この技術レポートの最新版は W3C標準・草案一覧でご覧いただけます。

編集上の更新に加え、2016年11月W3C勧告として公開されて以来の主な変更点は以下の通りです:

以前のバージョン以降の変更点詳細はコミット履歴をご覧ください。

ワーキンググループは編集者が未対応のバグ報告一覧を管理しています。

実装者は、この仕様が安定していないことに注意してください。議論に参加せず実装する場合、仕様が非互換な形で変更される可能性があります。最終的にCandidate Recommendation(CR)段階に到達する前に実装を検討するベンダーは、 GitHubリポジトリを追跡し議論に参加してください。

この文書はMedia Working Groupによって 勧告トラックを使用して作業草案として公開されました。

作業草案として公開されたことは、W3Cおよびそのメンバーによる承認を意味しません。

この文書はドラフトであり、随時更新・差し替え・廃止される可能性があります。進行中の作業以外のものとして引用するのは不適切です。

この文書は、 W3C 特許ポリシーの下で作成されています。 W3Cは、 公開特許開示リストを管理しており、グループ成果物に関連する特許開示や開示方法の案内も掲載しています。ある特許に 必須クレームが含まれると判断した場合は、 W3C特許ポリシー第6節に従って開示してください。

この文書は 2025年8月18日 W3Cプロセス文書に従って管理されています。

1. はじめに

このセクションは規範的ではありません。

この仕様は、JavaScriptが<audio>および<video>のメディアストリームを動的に構築できるようにします。MediaSourceオブジェクトを定義し、HTMLMediaElementのメディアデータのソースとして利用できます。MediaSourceオブジェクトは1つ以上のSourceBufferオブジェクトを持ちます。アプリケーションはSourceBufferオブジェクトにデータセグメントを追加し、システム性能やその他の要因に応じて追加データの品質を調整できます。SourceBufferオブジェクトのデータは、音声・映像・テキストのトラックバッファとして管理され、デコード・再生されます。これらの拡張で使用されるバイトストリーム仕様は、バイトストリームフォーマットレジストリ [MSE-REGISTRY] で参照できます。

メディアソース・パイプラインモデル図
1 メディアソース・パイプラインモデル図

1.1 目的

この仕様は以下の目的で設計されました:

この仕様で定義される内容:

2. 定義

アクティブ・トラックバッファ

トラックバッファのうち、符号化フレームを、enabled audioTracksselected videoTracks"showing" または "hidden" textTracks に提供するもの。これらのトラックはすべて、SourceBufferオブジェクトと、activeSourceBuffersリストに関連付けられます。

アペンドウィンドウ

表示タイムスタンプの範囲で、アペンド時に符号化フレームをフィルタリングします。アペンドウィンドウは、開始時刻と終了時刻で構成される連続した時間範囲です。この範囲内の表示タイムスタンプを持つ符号化フレームのみSourceBufferにアペンドできます。範囲外のフレームはフィルタリングされます。開始・終了時刻は、それぞれappendWindowStartおよびappendWindowEnd属性で制御されます。

符号化フレーム

表示タイムスタンプデコードタイムスタンプ符号化フレーム継続時間を持つメディアデータの単位。

符号化フレーム継続時間

符号化フレームの継続時間。映像・テキストの場合、フレームやテキストが表示されるべき時間を示します。音声の場合、フレーム内のすべてのサンプルの合計時間となります。例えば、44100Hzで441サンプルの音声フレームの場合、継続時間は10ミリ秒です。

符号化フレーム終了タイムスタンプ

符号化フレーム表示タイムスタンプ継続時間の合計。これは、そのフレーム直後の表示タイムスタンプを表します。

符号化フレームグループ

隣接しており、ギャップなく単調増加する符号化フレームデコードタイムスタンプを持つグループ。符号化フレーム処理アルゴリズムやabort()呼び出しで新しいグループが開始されます。

デコードタイムスタンプ

フレームおよび依存フレームの即時デコード・表示を仮定した場合、フレームをデコードする必要がある最も遅い時刻を示します(これは依存関係の最初のフレームの表示タイムスタンプと同じです)。プレゼンテーション順でフレームを順序通りデコードできる場合、デコードタイムスタンプがバイトストリームに存在しない場合は、表示タイムスタンプと同一です。

初期化セグメント

一連のバイトで、メディアセグメントのデコードに必要な初期化情報(コーデック初期化データ、トラックIDマッピング、タイムスタンプオフセット等)が含まれます。

バイトストリームフォーマットレジストリ [MSE-REGISTRY] のバイトストリームフォーマット仕様には、フォーマット固有の例が含まれています。

メディアセグメント

一部のメディアタイムラインのパケット化・タイムスタンプ付きメディアデータを含むバイト列。常に直近で追加された初期化セグメントに関連付けられます。

バイトストリームフォーマットレジストリ [MSE-REGISTRY] のバイトストリームフォーマット仕様には、フォーマット固有の例が含まれています。

MediaSourceオブジェクトURL

MediaSourceオブジェクトURLは、blob URLであり、createObjectURL()で生成されます。HTMLMediaElementにMediaSourceオブジェクトをアタッチするために使われます。

これらのURLはblob URLと同じですが、FileBlobに関する定義は、MediaSourceオブジェクトにも適用されます。

MediaSourceオブジェクトURLのオリジンは、relevant settings objectです。createObjectURL()呼び出し時のthisのオリジンとなります。

例えば、MediaSourceオブジェクトURLのオリジンは、メディア要素がcanvasによって利用される方法に影響します。

親MediaSource

SourceBufferオブジェクトの親MediaSourceは、それを生成したMediaSourceオブジェクトです。

表示開始時刻

表示開始時刻はプレゼンテーションの最も早い時点であり、初期の再生位置可能な最も早い位置を指定します。本仕様で作成されるすべてのプレゼンテーションは表示開始時刻が0です。

HTMLMediaElementbufferedが、現在の再生位置を含むTimeRangesを持つか判定するため、実装は現在の再生位置が表示開始時刻以降かつ最初のTimeRangesの開始より前の場合でも、1秒以内など十分短い時間であれば最初のTimeRanges再生を許容してよいことがあります。これは多重化ストリームでトラック開始が厳密に0でないことが多いためです。実装はこの許容とは関係なく、実際のバッファ範囲を報告しなければなりません

表示区間

符号化フレームの表示区間は、表示タイムスタンプから、表示タイムスタンプ継続時間までの区間です。例えば、表示タイムスタンプが10秒で継続時間が100ミリ秒なら、表示区間は[10-10.1)です。範囲の開始は含み、終了は含みません。

表示順序

符号化フレームがプレゼンテーションで表示される順序。表示順序は、符号化フレームを表示タイムスタンプの単調増加順で並べることで実現されます。

表示タイムスタンプ

プレゼンテーション内の特定時刻への参照。符号化フレーム内の表示タイムスタンプは、そのフレームが表示されるべき時刻を示します。

ランダムアクセスポイント

メディアセグメント内で、連続再生・デコードを前のデータに頼らず開始できる位置。映像ならIフレームの位置が該当することが多く、音声は多くのフレームがランダムアクセス可能。映像トラックはランダムアクセスポイントが稀なので、多重化ストリームでもその位置が重要になります。

SourceBuffer バイトストリームフォーマット仕様

SourceBufferインスタンスが受け付けるバイトストリームのフォーマットを記述するバイトストリームフォーマット仕様SourceBufferオブジェクトの仕様は、addSourceBuffer()呼び出し時のtypeで初期選択され、changeType()呼び出しで変更できます。

SourceBuffer構成

単一のMediaSourceインスタンスが所有する、1つ以上のSourceBufferオブジェクトに分散する特定トラック群。

実装は少なくとも以下の構成のいずれかをサポートしなければなりません

  • 音声トラックおよび/または映像トラックを持つ単一のSourceBuffer
  • 1つは音声トラックのみ、もう1つは映像トラックのみを扱う2つのSourceBuffer

MediaSourceオブジェクトは上記の各構成をサポートしなければなりませんが、同時に複数構成のサポートは必須ではありません。同時・追加構成のサポートは実装品質に依存します。

トラック記述

バイトストリームフォーマット固有の構造で、トラックID、コーデック設定、その他メタデータを提供します。単一の初期化セグメント内の各トラック記述には一意なトラックIDが必要です。トラックIDが一意でない場合、ユーザーエージェントはappend errorアルゴリズムを実行しなければなりません

トラックID

トラックIDはバイトストリームフォーマット固有の識別子で、ストリームの特定区間がどのトラックに属するかを示します。トラック記述内のトラックIDは、メディアセグメント内の該当区間を識別します。

3. MediaSource インターフェース

MediaSource インターフェースは、 HTMLMediaElement用のメディアデータのソースを表します。 このソースのreadyStateや、 プレゼンテーションにメディアデータを追加可能なSourceBufferオブジェクトのリストを管理します。 MediaSourceオブジェクトはウェブアプリケーションによって作成され、HTMLMediaElementにアタッチされます。 アプリケーションはSourceBufferオブジェクトを sourceBuffersで利用し、本ソースへメディアデータを追加します。 HTMLMediaElementは再生時にMediaSourceオブジェクトからメディアデータを取得します。

MediaSourceオブジェクトは、[[live seekable range]]という内部スロットを持ち、これは 正規化されたTimeRangesオブジェクトを保持します。 オブジェクト生成時には空のTimeRangesオブジェクトで初期化され、 setLiveSeekableRange()clearLiveSeekableRange()で管理されます。 また、10. HTMLMediaElement拡張HTMLMediaElementseekable の挙動変更にも利用されます。

MediaSourceオブジェクトは、[[has ever been attached]]という内部スロットも持ち、これはboolean型です。 オブジェクト生成時にfalseで初期化され、拡張された HTMLMediaElementリソース取得アルゴリズムメディア要素へのアタッチアルゴリズム)でtrueに設定されます。 拡張されたリソース取得アルゴリズムは、 この内部スロットを用いて、MediaSourceMediaSourceHandleHTMLMediaElementsrcObject 属性に設定してアタッチする際に条件付きで失敗させるために使用します。

WebIDLenum ReadyState {
  "closed",
  "open",
  "ended",
};
closed
このソースは現在メディア要素にアタッチされていないことを示します。
open
ソースがメディア要素によってオープンされ、 SourceBufferオブジェクト(MediaSourcesourceBuffers)へデータ追加可能な状態です。
ended
ソースはまだメディア要素にアタッチされていますが、 MediaSourceendOfStream()が呼び出されています。
Issue 276: MSE-in-Workers: 「closing」readyStateを追加して、クローズ中の新しい`InvalidStateError`例外を説明することを検討 mse-in-workers
WebIDLenum EndOfStreamError {
  "network",
  "decode",
};
network

再生を終了し、ネットワークエラーの発生を通知します。

JavaScriptアプリケーションは、ネットワークエラーで再生を終了する際にこのステータスコードを利用すべきです。 例:メディアデータ取得中にネットワークエラーが発生した場合。

decode

再生を終了し、デコードエラーの発生を通知します。

JavaScriptアプリケーションは、デコードエラーで再生を終了する際にこのステータスコードを利用すべきです。 例:帯域外のメディアデータ処理時にパースエラーが発生した場合。

WebIDL[Exposed=(Window,DedicatedWorker)]
interface MediaSource : EventTarget {
    constructor();

    [SameObject, Exposed=DedicatedWorker]
    readonly  attribute MediaSourceHandle handle;
    readonly  attribute SourceBufferList sourceBuffers;
    readonly  attribute SourceBufferList activeSourceBuffers;
    readonly  attribute ReadyState readyState;

    attribute unrestricted double duration;
    attribute EventHandler onsourceopen;
    attribute EventHandler onsourceended;
    attribute EventHandler onsourceclose;

    static readonly attribute boolean canConstructInDedicatedWorker;

    SourceBuffer addSourceBuffer(DOMString type);
    undefined removeSourceBuffer(SourceBuffer sourceBuffer);
    undefined endOfStream(optional EndOfStreamError error);
    undefined setLiveSeekableRange(double start, double end);
    undefined clearLiveSeekableRange();
    static boolean isTypeSupported(DOMString type);
};

3.1 handle 属性

この属性は、専用ワーカーのMediaSourceオブジェクトを HTMLMediaElementsrcObject 経由でアタッチするのに役立つハンドルを保持します。このhandleは、このMediaSourceオブジェクトに対する属性アクセス間で同一のオブジェクトですが、 各MediaSourceオブジェクトごとに異なります。

この仕様は将来的に、メインWindowコンテキスト上のMediaSource オブジェクトでもこの属性を可視化できるようになる可能性があります。その場合、属性アクセス時に例外が発生するなど、後方非互換な変更を防ぐため、仕様上の配慮が必要となります。

取得時、以下の手順を実行します:

  1. このMediaSourceオブジェクトのhandleが まだ作成されていない場合、次の手順を実行:
    1. created handleに、新しい MediaSourceHandleオブジェクトと関連リソースを生成し、内部的に このMediaSourceへリンクする。
    2. 属性値をcreated handleに更新する。
  2. この属性値であるMediaSourceHandle オブジェクトを返す。

3.2 sourceBuffers 属性

この属性は、このMediaSourceに関連付けられた SourceBufferオブジェクトのリストを保持します。 MediaSourcereadyStateが"closed"の場合、 このリストは空になります。readyStateが"open"に遷移すると、 addSourceBuffer()で このリストにSourceBufferオブジェクトを追加できます。

3.3 activeSourceBuffers 属性

この属性は、sourceBuffersのうち、 selected な映像トラック、enabled な音声トラック、そして "showing""hidden" なテキストトラックを提供しているSourceBufferの部分集合を保持します。

このリスト内のSourceBufferオブジェクトは、 sourceBuffers属性内での順序と同じ順番で なければなりません。例:sourceBuffers[0]とsourceBuffers[3]のみが activeSourceBuffersの場合、 activeSourceBuffers[0] sourceBuffers[0]と等しく、activeSourceBuffers[1] sourceBuffers[3]と等しくなります。

3.15.5 選択/有効トラック状態の変更で、この属性の更新方法が説明されています。

3.4 readyState 属性

MediaSourceオブジェクトの現在の状態を示します。 MediaSource が生成された時、readyStateは"closed"に 設定されていなければなりません

3.5 duration 属性

Webアプリケーションがプレゼンテーションのduration(継続時間)を設定できます。MediaSourceオブジェクト生成時、durationは最初にNaNとなります。

取得時、以下の手順を実行します:

  1. readyState属性が"closed"の場合、 NaNを返して手順を中止する。
  2. 属性の現在値を返す。

設定時、以下の手順を実行します:

  1. 設定値が負またはNaNなら、TypeError 例外を投げて手順を中止する。
  2. readyState属性が"open"でない場合、 InvalidStateError 例外を投げて手順を中止する。
  3. updating属性が SourceBufferのいずれかでtrueなら、 InvalidStateError 例外を投げて手順を中止する。
  4. new durationにこの属性へ代入される値をセットし、 duration changeアルゴリズムを実行する。

    duration changeアルゴリズムは、現在バッファされている end timeがより大きい符号化フレームがあれば、new durationを より大きい値に調整します。

    appendBuffer()endOfStream() は、状況によってdurationを更新する可能性があります。

3.6 canConstructInDedicatedWorker 属性

trueを返します。

この属性により、メインスレッド・専用ワーカーでのMediaSourceオブジェクトの 生成・利用のサポート有無を機能検出でき、高遅延な検出ポリフィル(専用ワーカーからの生成試行など)を不要にします。

3.7 addSourceBuffer() メソッド

新しいSourceBuffersourceBuffersへ追加します。

  1. typeが空文字列なら、TypeError 例外を投げて手順を中止する。
  2. typeがサポートされないMIMEタイプ、もしくは他のSourceBufferオブジェクトに指定されたtypeとの組み合わせでサポートされないMIMEタイプを含む場合、 NotSupportedError 例外を投げて手順を中止する。
  3. ユーザーエージェントがこれ以上SourceBufferオブジェクトを扱えない場合、または typeに基づいてSourceBufferを生成すると サポートされないSourceBuffer構成となる場合、 QuotaExceededError 例外を投げて手順を中止する。

    例:ユーザーエージェントは、メディア要素がHAVE_METADATA readyStateに達した場合、QuotaExceededError 例外を投げることがあります。これは、再生中に新しいトラック追加をサポートしないメディアエンジンの場合などです。

  4. readyState属性が"open"状態でない場合、 InvalidStateError 例外を投げて手順を中止する。
  5. bufferに、ManagedSourceBufferthisManagedMediaSource の場合)または、それ以外の場合はSourceBufferの新しいインスタンス(関連リソース付き)をセットする。
  6. buffer[[generate timestamps flag]]を、 Media Source Extensions™ Byte Stream Format Registryの該当typeの "Generate Timestamps Flag"列の値に設定する。
  7. buffer[[generate timestamps flag]]がtrueなら、 buffermodeを"sequence"に、 そうでなければ"segments"に設定する。
  8. Append bufferthissourceBuffersへ追加する。
  9. タスクをキューして、 addsourcebufferイベントを発火 させる(thisのsourceBuffers対象)。
  10. bufferを返す。

3.8 removeSourceBuffer() メソッド

SourceBuffersourceBuffersから削除します。

  1. sourceBuffersourceBuffersに含まれていない場合は、NotFoundError例外を投げて手順を中止します。
  2. sourceBuffer.updating属性がtrueの場合、次の手順を実行します:
    1. buffer appendアルゴリズムが実行中なら中止します。
    2. sourceBuffer.updating属性をfalseに設定します。
    3. タスクをキューして、abortイベントを発火します(sourceBuffer対象)。
    4. タスクをキューして、updateendイベントを発火します(sourceBuffer対象)。
  3. SourceBuffer audioTracks listsourceBuffer.audioTracksから取得します。
  4. SourceBuffer audioTracks listが空でない場合、次の手順を実行します:
    1. SourceBuffer audioTracks list内の各AudioTrackオブジェクトについて、次の手順を実行します:
      1. sourceBuffer属性をnullに設定します。
      2. AudioTrack オブジェクトをSourceBuffer audioTracks listから削除します。

        これによりAudioTrackList [HTML]のロジックで、タスクをキューし、 removetrackイベントTrackEventtrack 属性にこのオーディオトラックオブジェクトをセット)をSourceBuffer audioTracks list上で発火します。さらに、enabled 属性がこの削除手順開始時にtrueだった場合、AudioTrackList [HTML]のロジックでchangeイベントも発火します。

      3. mirror if necessaryアルゴリズムを使い、Windowで 以下の手順を実行し、(専用ワーカー生成の場合はWindow側のmirror)メディア要素からAudioTrack オブジェクトを削除:
        1. HTMLMediaElement audioTracks listを HTMLMediaElementのaudioTracks 属性から取得します。
        2. AudioTrack オブジェクトをHTMLMediaElement audioTracks listから削除します。

          これによりAudioTrackList [HTML]のロジックで removetrackイベント(TrackEvent のtrack属性にこのオーディオトラックオブジェクトをセット)をHTMLMediaElement audioTracks list上で発火します。さらに、enabled属性が削除手順開始時にtrueだった場合はchangeイベントも発火します。

  5. SourceBuffer videoTracks listsourceBuffer.videoTracksから取得します。
  6. SourceBuffer videoTracks listが空でない場合、次の手順を実行します:
    1. SourceBuffer videoTracks list内の各VideoTrackオブジェクトについて、次の手順を実行します:
      1. sourceBuffer属性をnullに設定します。
      2. VideoTrack オブジェクトをSourceBuffer videoTracks listから削除します。

        これによりVideoTrackList [HTML]のロジックで、タスクをキューし、 removetrackイベントTrackEventtrack 属性にこのビデオトラックオブジェクトをセット)をSourceBuffer videoTracks list上で発火します。さらに、selected 属性がこの削除手順開始時にtrueだった場合、changeイベントも発火します。

      3. mirror if necessaryアルゴリズムを使い、Windowで 以下の手順を実行し、(専用ワーカー生成の場合はWindow側のmirror)メディア要素からVideoTrack オブジェクトを削除:
        1. HTMLMediaElement videoTracks listを HTMLMediaElementのvideoTracks 属性から取得します。
        2. VideoTrack オブジェクトをHTMLMediaElement videoTracks listから削除します。

          これによりVideoTrackList [HTML]のロジックで removetrackイベント(TrackEvent のtrack属性にこのビデオトラックオブジェクトをセット)をHTMLMediaElement videoTracks list上で発火します。さらに、selected属性が削除手順開始時にtrueだった場合はchangeイベントも発火します。

  7. SourceBuffer textTracks listsourceBuffer.textTracksから取得します。
  8. SourceBuffer textTracks listが空でない場合、次の手順を実行します:
    1. SourceBuffer textTracks list内の各TextTrackオブジェクトについて、次の手順を実行します:
      1. sourceBuffer属性をnullに設定します。
      2. TextTrack オブジェクトをSourceBuffer textTracks listから削除します。

        これによりTextTrackList [HTML]のロジックで、タスクをキューし、 removetrackイベントTrackEventtrack 属性にこのテキストトラックオブジェクトをセット)をSourceBuffer textTracks list上で発火します。さらに、mode 属性がこの削除手順開始時に"showing"または"hidden"だった場合、changeイベントも発火します。

      3. mirror if necessaryアルゴリズムを使い、Windowで 以下の手順を実行し、(専用ワーカー生成の場合はWindow側のmirror)メディア要素からTextTrack オブジェクトを削除:
        1. HTMLMediaElement textTracks listを HTMLMediaElementのtextTracks 属性から取得します。
        2. TextTrack オブジェクトをHTMLMediaElement textTracks listから削除します。

          これによりTextTrackList [HTML]のロジックで removetrackイベント(TrackEvent のtrack属性にこのテキストトラックオブジェクトをセット)をHTMLMediaElement textTracks list上で発火します。さらに、mode属性が削除手順開始時に"showing"または"hidden"だった場合はchangeイベントも発火します。

  9. sourceBufferactiveSourceBuffersに含まれる場合、 sourceBufferactiveSourceBuffersから削除し、 タスクをキューして removesourcebufferイベントSourceBufferListactiveSourceBuffersから返される)で発火します。
  10. sourceBuffersourceBuffersから削除し、 タスクをキューして removesourcebufferイベントSourceBufferListsourceBuffersから返される)で発火します。
  11. sourceBufferのすべてのリソースを破棄します。

3.9 endOfStream() メソッド

ストリームの終了を通知します。

  1. readyState属性が"open"状態でないなら、 InvalidStateError 例外を投げて手順を中止します。
  2. updating属性が SourceBufferのいずれかでtrueなら、 InvalidStateError 例外を投げて手順を中止します。
  3. end of streamアルゴリズムを、errorパラメータに errorを指定して実行します。

3.10 setLiveSeekableRange() メソッド

[[live seekable range]] を更新します。この属性は 10. HTMLMediaElement拡張HTMLMediaElementseekable の挙動変更に利用されます。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行します:

  1. readyState属性が"open"でないなら、 InvalidStateError 例外を投げて手順を中止します。
  2. startが負またはendより大きい場合、 TypeError例外を投げて手順を中止します。
  3. [[live seekable range]]を 新しい正規化されたTimeRangesオブジェクト(開始位置がstart、終了位置がendの単一範囲)に設定します。

3.11 clearLiveSeekableRange() メソッド

[[live seekable range]] を更新します。この属性は 10. HTMLMediaElement拡張HTMLMediaElementseekable の挙動変更に利用されます。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行します:

  1. readyState属性が"open"でないなら、 InvalidStateError 例外を投げて手順を中止します。
  2. [[live seekable range]]に範囲が含まれている場合は、 [[live seekable range]]を新しい空の TimeRangesオブジェクトに設定します。

3.12 isTypeSupported() メソッド

指定したMIMEタイプに対して、MediaSourceSourceBufferオブジェクトを生成できるかどうかをチェックします。

このメソッドがtrueを返した場合、それはMediaSourceの実装が 指定されたMIMEタイプに対してSourceBufferオブジェクトを生成できることだけを示します。 addSourceBuffer() の呼び出しは、十分なリソースがなければ失敗するべきです

このメソッドがtrueを返す場合、 HTMLMediaElementcanPlayType() も"maybe"または"probably"を返すことを意味します。HTMLMediaElementが再生できないタイプをMediaSourceがサポートすることはありえません。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行します:

  1. typeが空文字列なら、falseを返します。
  2. typeが有効なMIMEタイプ文字列でない場合、falseを返します。
  3. typeがMediaSourceのサポートしないメディアタイプまたはサブタイプを含む場合、falseを返します。
  4. typeがMediaSourceのサポートしないコーデックを含む場合、falseを返します。
  5. MediaSourceが指定されたメディアタイプ・サブタイプ・コーデックの組み合わせをサポートしない場合、falseを返します。
  6. trueを返します。

3.13 イベント概要

イベント名 インターフェース 発生条件
sourceopen Event MediaSourcereadyStateが "closed" から"open"へ、 または"ended"から"open"へ遷移したとき。
sourceended Event MediaSourcereadyStateが "open" から"ended"へ遷移したとき。
sourceclose Event MediaSourcereadyStateが "open" から"closed"、 または"ended"から"closed"へ遷移したとき。

3.14 クロスコンテキスト通信モデル

WindowHTMLMediaElementDedicatedWorkerGlobalScopeMediaSourceにアタッチされると、 各コンテキストは互いの情報に依存するアルゴリズムを持ちます。

HTMLMediaElementWindow コンテキストのみで公開されますが、本仕様で定義されたMediaSourceおよび関連オブジェクトは Window およびDedicatedWorkerGlobalScope コンテキスト両方で公開されます。これにより、アプリケーションはどちらのコンテキストでもMediaSourceオブジェクトを構築し、 MediaSourceオブジェクトURLMediaSourceHandle を使って、Window コンテキストの HTMLMediaElement にアタッチできます(メディア要素へのアタッチアルゴリズム参照)。 MediaSourceオブジェクトは Transferableではなく、 生成されたコンテキストでのみ可視です。

残りのこのセクションでは、 Window のメディア要素をDedicatedWorkerGlobalScopeMediaSourceにアタッチする際の情報遅延を制限するモデルを説明します。 モデルではメッセージパッシングによる通信を記述しますが、実装は共有メモリやロックなどより高速な通信手段を選択してもよいです。 WindowMediaSourceへのアタッチは、情報がすでに同期的に得られるため、 コンテキスト間の通信は不要です。

MediaSourceDedicatedWorkerGlobalScopeで構築された場合、 [[port to main]]という内部スロットを持ち、 アタッチ時にセットされ、デタッチ時にnullとなる MessagePortを保持します。 Window[[port to main]]は常にnullです。

本仕様で拡張されたHTMLMediaElementDedicatedWorkerGlobalScopeMediaSourceにアタッチされる場合も同様に、 [[port to worker]]内部スロット(アタッチ時にセット、デタッチ時にnull)と、 [[channel with worker]]内部スロット(MessageChannelを保持し、アタッチ時セット、デタッチ時null)を持ちます。 [[port to worker]][[channel with worker]] は、DedicatedWorkerGlobalScopeMediaSourceにアタッチされていない限りnullです。

本仕様のアルゴリズムで、WindowHTMLMediaElement からアタッチ先のDedicatedWorkerGlobalScopeMediaSource、またはその逆方向へ情報通信が必要な場合、 これらの内部ポートを暗黙的に使い、対応する側へメッセージをポストします。メッセージの暗黙ハンドラは、アルゴリズムで記述された手順を実行します。

3.15 アルゴリズム

3.15.1 メディア要素へのアタッチ

MediaSourceをメディア要素にアタッチする仕組みは、MediaSourceオブジェクトがどこで構築されたか、すなわちWindowなのか DedicatedWorkerGlobalScopeなのかに応じて異なります。

もしresource fetch algorithmが、メディア提供オブジェクトとしてMediaSourceオブジェクト、MediaSourceHandleオブジェクト、またはオブジェクトがMediaSourceであるURLレコードで呼び出された場合は、modeをlocalにし、(そうでなければmodeをremoteに設定しうる)resource fetch algorithmの最初の手順をスキップして、そのresource fetch algorithmの実行を続けます。

resource fetch algorithmの最初の手順は、オブジェクトがメディア提供オブジェクトであるURLレコードに対してlocalモードを選択するよう、最終的には整合される見込みです。意図としては、HTMLMediaElementsrc属性や、選択された子 sourcesrc 属性が、当該src属性が最後に変更された時点でMediaSourceオブジェクトURLに一致するblob:URLであれば、そのMediaSourceオブジェクトが、resource fetch algorithmのlocalモードのロジックにおけるメディア提供オブジェクトかつ現在のメディアリソースとして用いられるというものです。これはまた、MediaSourceオブジェクトがアタッチされている場合には、preload属性の順守を含むremoteモードのロジックがスキップされることも意味します。たとえ[HTML]にそのような変更が将来的に行われたとしても、現在のメディアリソースがMediaSourceオブジェクトである場合には、localモードのロジックの冒頭で以下の手順を実行する必要があります。

resource fetch algorithmの「Otherwise(mode is local)」節の冒頭で、以下の追加手順を実行します。

メディア要素のリソース選択アルゴリズムをトリガーしたアクションに対して、これらの手順は非同期です。resource fetch algorithmは、リソース選択アルゴリズムを呼び出したタスクが継続でき、安定状態に到達した後に実行されます。実装は、以下の「Otherwise」節の手順を、MediaSourceオブジェクトが使用可能になるまで遅延させてもかまいません。

  1. もしresource fetch algorithmが、メディア提供オブジェクトとしてMediaSourceオブジェクト、MediaSourceHandleオブジェクト、またはオブジェクトがMediaSourceであるURLレコードで呼び出されているなら:
    メディア提供オブジェクトが、オブジェクトがMediaSourceであるURLレコードで、かつそれがDedicatedWorkerGlobalScopeで構築された場合( 例えばMediaSourceオブジェクトURLDedicatedWorkerGlobalScopeから用いようとする場合 など)
    resource fetch algorithmmedia data processing steps listにある、"If the media data cannot be fetched at all, due to network errors, causing the user agent to give up trying to fetch the resource"の手順を実行します。
    これは、DedicatedWorkerのMediaSourceアタッチにMediaSourceオブジェクトURLを使用できないようにするためのものです。MediaSourcehandleをDedicatedWorkerからWindowコンテキストへ転送し、メディア要素のsrcObject属性に代入することが、そのようなMediaSourceをアタッチする唯一の方法です。
    メディア提供オブジェクトが、MediaSourceHandleで、その[[Detached]]内部スロットがtrueである場合
    resource fetch algorithmmedia data processing steps listにある、"If the media data cannot be fetched at all, due to network errors, causing the user agent to give up trying to fetch the resource"の手順を実行します。
    メディア提供オブジェクトが、基礎となるMediaSource[[has ever been attached]]内部スロットがtrueであるMediaSourceHandleである場合
    resource fetch algorithmmedia data processing steps listにある、"If the media data cannot be fetched at all, due to network errors, causing the user agent to give up trying to fetch the resource"の手順を実行します。
    これは、基礎となるMediaSourceが、たとえWindowで構築され、以前にMediaSourceオブジェクトURLを用いて読み込まれていたとしても、MediaSourceHandleを使って複数回読み込まれることを防ぎます。 ただし、これはWindowMediaSourceに対して、その後にMediaSourceオブジェクトURLを用いることが成功する可能性を妨げるものではありません。
    readyStateが "closed"に設定されていない場合
    resource fetch algorithmmedia data processing steps listにある、"If the media data cannot be fetched at all, due to network errors, causing the user agent to give up trying to fetch the resource"の手順を実行します。
    それ以外の場合
    1. MediaSource[[has ever been attached]]内部スロットをtrueに設定します。
    2. メディア要素のdelaying-the-load-event-flagを falseに設定します。
    3. MediaSourceDedicatedWorkerGlobalScopeで構築されている場合、ワーカー側のアタッチ通信をセットアップし、MediaSourceをopenにします:
      1. [[channel with worker]]に新しい MessageChannelを設定します。
      2. [[port to worker]]を、 port1[[channel with worker]]の値)に設定します。
      3. StructuredSerializeWithTransferを実行し、 port2[[channel with worker]]の値)を値およびtransferListの唯一のメンバーとして渡し、結果をserialized port2とします。
      4. Queue a taskを、MediaSourceDedicatedWorkerGlobalScope上で行い、次を実施します
        1. StructuredDeserializeWithTransferを、serialized port2DedicatedWorkerGlobalScoperealmで実行し、転送されたport2のデシリアライズされたクローンを[[port to main]]に設定します([[channel with worker]]の値)。
        2. readyState属性を "open"に設定します。
        3. Queue a taskで、fire an eventを行い、sourceopenという名前のイベントを MediaSourceで発火します。
      それ以外の場合、MediaSourceWindowで構築されています:
      1. [[channel with worker]]を nullに設定します。
      2. [[port to worker]]を nullに設定します。
      3. [[port to main]]を nullに設定します。
      4. readyState属性を "open"に設定します。
      5. Queue a taskで、fire an eventを行い、sourceopenという名前のイベントを MediaSourceで発火します。
    4. resource fetch algorithmを、残りの"Otherwise (mode is local)"の手順を実行することで継続します。要件は次のとおりです:
      1. resource fetch algorithmまたはmedia data processing steps listにおける「the download」「bytes received」「whenever new data for the current media resource becomes available」への言及は、appendBuffer()経由で渡されるデータを指します。
      2. resource fetch algorithmおよびmedia data processing steps listにおけるHTTPへの参照は、MediaSourceがアタッチされているときはHTMLMediaElementがHTTP経由でメディアデータを取得しないため、適用されません。

アタッチされたMediaSourceは、resource fetch algorithmのremoteモードの手順を使用しないため、メディア要素は「suspend」イベントを発火しません。将来のこの仕様のバージョンでは、MediaSourceがアタッチされたメディア要素から「progress」および「stalled」イベントを削除する可能性が高いですが、この版に準拠するユーザーエージェントは、実装が安定した後で[HTML]側の参照が変更されたため、これら2つのイベントを引き続き発火する場合があります。

3.15.2 メディア要素からのデタッチ

以下の手順は、メディア要素が NETWORK_EMPTY に遷移し、メディア要素で タスクをキューして イベントを発火 (名前は emptied) するあらゆる場合に実行されます。これらの手順は、遷移の直前に実行される SHOULD があります。

  1. MediaSourceDedicatedWorkerGlobalScope で構築された場合:
    1. MediaSource に対して、内部の detach メッセージを [[port to worker]] にポストして通知する。
    2. [[port to worker]] を null に設定する。
    3. [[channel with worker]] を null に設定する。
    4. この detach 通知に対する暗黙のメッセージハンドラは、 残りの手順を DedicatedWorkerGlobalScopeMediaSource で実行する。
    それ以外の場合、MediaSourceWindow で構築されている:
    残りの手順は WindowMediaSource で続行する。
  2. [[port to main]] を null に設定する。
  3. readyState 属性を "closed" に設定する。
  4. thisManagedMediaSource の場合、 streaming 属性を false に設定する。
  5. duration を NaN に更新する。
  6. SourceBuffer オブジェクトをすべて activeSourceBuffers から削除する。
  7. タスクをキューして、 イベントを発火し、 名前が removesourcebuffer のイベントを activeSourceBuffers で発火する。
  8. SourceBuffer オブジェクトをすべて sourceBuffers から削除する。
  9. タスクをキューして、 イベントを発火し、 名前が removesourcebuffer のイベントを sourceBuffers で発火する。
  10. タスクをキューして、 イベントを発火し、 名前が sourceclose のイベントを MediaSource で発火する。

今後、このアルゴリズムは、アタッチされている MediaSource(存在する場合)を メディア要素からデタッチしなければならないあらゆるケースで、外部から呼び出して実行することを意図しています。 これは、メディア要素が NETWORK_EMPTY に遷移する際に加えて、あるいはその代わりに、HTMLMediaElement [HTML] の load() などの操作や resource fetch algorithm の失敗時に呼び出される MAY があります。 リソース取得アルゴリズムの失敗とは、resource fetch algorithm か resource selection algorithm のいずれかを中断する失敗を指しますが、 [HTML] の「Final step」は デタッチをトリガーする失敗とは見なされません。

3.15.3 シーク

seek アルゴリズム の 「ユーザーエージェントが、新しい再生位置のメディアデータが利用可能かどうかを判断し、 もし利用可能であれば、その位置を再生できるだけのデータをデコードするまで待機する」手順の一部として、 次の手順を実行します。

  1. メディア要素は、SourceBuffer オブジェクト( activeSourceBuffers 内) のそれぞれについて、new playback position を含む メディアセグメント を探します。現在の HTMLMediaElementbuffered 属性の値に含まれる TimeRanges 内の任意の位置には、その位置に必要なすべてのメディアセグメントがバッファされています。

    new playback position が、 TimeRangesHTMLMediaElementbuffered) のいずれにも含まれていない場合
    1. HTMLMediaElementreadyState 属性が HAVE_METADATA より大きい場合、 HTMLMediaElementreadyState 属性を HAVE_METADATA に設定する。

      HTMLMediaElement のレディ状態 [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性があります。

    2. メディア要素は、ある appendBuffer() 呼び出しによって 符号化フレーム処理 アルゴリズムが実行され、 HTMLMediaElementreadyState 属性が HAVE_METADATA より大きい値に設定されるまで待機する。

      ウェブアプリケーションは、 bufferedHTMLMediaElementbuffered を用いて、再生再開に必要なものを判断できます。

    それ以外の場合
    続行

    readyState 属性が "ended" で、 new playback position が現在の HTMLMediaElementbuffered に含まれる TimeRanges 内にある場合には、現在選択または有効なトラックバッファの最大範囲終了タイムスタンプが new playback position より小さくても、ここでシーク操作は完了まで継続しなければなりません。 この条件は、 buffered のロジックにより、 readyState が "ended" のときにのみ発生するはずです。

  2. メディア要素はすべてのデコーダーをリセットし、適切な initialization segment のデータで各デコーダーを初期化する。
  3. メディア要素は、active track buffers から coded frames をデコーダーへ供給し、 new playback position の直前で最も近い random access point から開始する。
  4. seek アルゴリズム を「安定状態を待機」の手順から再開する。

3.15.4 SourceBuffer 監視

再生中に定期的に次の手順を実行し、SourceBuffer オブジェクト( activeSourceBuffers 内)が、 途切れのない再生を保証するのに十分なデータ を持っていることを確認します。 activeSourceBuffers の変更も、 状態遷移をトリガーする条件に影響するため、これらの手順の実行原因となります。

途切れのない再生を保証するのに十分なデータ を持つとは、 ユーザーエージェントが、意味のある時間停止することなくプレゼンテーションを再生できるだけのデータが現在あると判断する、 実装固有の条件です。この条件は常に評価され、メディア要素を HAVE_ENOUGH_DATA レディ状態に入出するタイミングを決定します。これらの遷移は、それぞれ、ユーザーエージェントが十分なデータがバッファされていると考えているのか、さらなるデータが必要なのかを示します。

実装は、バッファ済みバイト数、バッファ済み時間、アペンド速度、その他適切と見なす任意の指標を用いて、 いつ十分なデータがあるかを判断しても MAY です。使用する指標は再生中に変化する MAY があるため、 ウェブアプリケーションは、より多くのデータが必要かどうかの判断には HTMLMediaElementreadyState の値のみに依拠する SHOULD があります。

メディア要素がより多くのデータを必要とする場合、ユーザーエージェントは、 SHOULD 早めに HAVE_ENOUGH_DATA から HAVE_FUTURE_DATA に遷移させ、再生の中断を引き起こすことなくウェブアプリケーションが応答できるようにすべきです。 例えば、現在の再生位置がバッファ済みデータの末尾の 500ms 手前で遷移すれば、再生が停止する前にアプリケーションはおよそ 500ms でデータを追加できます。

HTMLMediaElementreadyState 属性が HAVE_NOTHING と等しい場合:
  1. これらの手順を中止する。
HTMLMediaElementbuffered が、現在の再生位置に対応する TimeRanges を含まない場合:
  1. HTMLMediaElementreadyState 属性を HAVE_METADATA に設定する。

    HTMLMediaElement のレディ状態 [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性があります。

  2. これらの手順を中止する。
HTMLMediaElementbuffered が、現在の再生位置を含み、かつ 途切れのない再生を保証するのに十分なデータ を含む TimeRanges を含む場合:
  1. HTMLMediaElementreadyState 属性を HAVE_ENOUGH_DATA に設定する。

    HTMLMediaElement のレディ状態 [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性があります。

  2. 以前に HAVE_CURRENT_DATA への遷移によって一時停止していた場合、この時点で再生が再開されることがある。
  3. これらの手順を中止する。
HTMLMediaElementbuffered が、現在の再生位置を含み、かつ現在の再生位置よりも先の時間も含む TimeRanges を含む場合、次の手順を実行する:
  1. HTMLMediaElementreadyState 属性を HAVE_FUTURE_DATA に設定する。

    HTMLMediaElement のレディ状態 [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性があります。

  2. 以前に HAVE_CURRENT_DATA への遷移によって一時停止していた場合、この時点で再生が再開されることがある。
  3. これらの手順を中止する。
HTMLMediaElementbuffered が、現在の再生位置で終了し、その直後の時間をカバーする範囲を持たない TimeRanges を含む場合:
  1. HTMLMediaElementreadyState 属性を HAVE_CURRENT_DATA に設定する。

    HTMLMediaElement のレディ状態 [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性があります。

  2. メディア要素は、メディアタイムライン を進めるのに十分なデータを持たないため、 この時点で再生は一時停止される。
  3. これらの手順を中止する。

3.15.5 選択/有効トラック状態の変更

再生中、activeSourceBuffers は、 ビデオトラックの selected、 オーディオトラックの enabled、 あるいはテキストトラックの mode が変更された場合に更新する必要があります。これらのうち 1 つ以上が変更されたときは、以下の手順に従う必要があります。 また、MediaSourceDedicatedWorkerGlobalScope で構築された場合、 以前に内部の create track mirror メッセージの暗黙ハンドラによって作成されたトラックの Window ミラーに発生する各変更も、 [[port to worker]] にポストされる内部の update track state メッセージを用いて 対応する DedicatedWorkerGlobalScope のトラックにも反映しなければなりません MUST。暗黙ハンドラは変更を行い、以下の手順を実行します。 同様に、 DedicatedWorkerGlobalScope のトラックに発生する各変更も、 [[port to main]] にポストされる内部の update track state メッセージを用いて 対応する Window のミラーにも反映しなければなりません MUST。暗黙ハンドラはミラーに変更を適用します。

選択されたビデオトラックが変更された場合は、以下の手順を実行する:
  1. 以前に選択されていたビデオトラックに関連付けられている SourceBuffer が、 他の有効なトラックと関連付けられていない場合、以下の手順を実行する:
    1. その SourceBufferactiveSourceBuffers から削除する。
    2. タスクをキューして、 イベントを発火し、 名前が removesourcebuffer のイベントを activeSourceBuffers で発火する。
  2. 新たに選択されたビデオトラックに関連付けられている SourceBuffer が、 まだ activeSourceBuffers に含まれていない場合、以下の手順を実行する:
    1. その SourceBufferactiveSourceBuffers に追加する。
    2. タスクをキューして、 イベントを発火し、 名前が addsourcebuffer のイベントを activeSourceBuffers で発火する。
あるオーディオトラックが無効になり、そのトラックに関連付けられている SourceBuffer が、他の有効または選択トラックと関連付けられていない場合、次の手順を実行する:
  1. そのオーディオトラックに関連付けられている SourceBufferactiveSourceBuffers から削除する。
  2. タスクをキューして、 イベントを発火し、 名前が removesourcebuffer のイベントを activeSourceBuffers で発火する。
あるオーディオトラックが有効になり、そのトラックに関連付けられている SourceBuffer が、 まだ activeSourceBuffers に含まれていない場合、次の手順を実行する:
  1. そのオーディオトラックに関連付けられている SourceBufferactiveSourceBuffers に追加する。
  2. タスクをキューして、 イベントを発火し、 名前が addsourcebuffer のイベントを activeSourceBuffers で発火する。
テキストトラックの mode"disabled" になり、そのトラックに関連付けられている SourceBuffer が、 他の有効または選択トラックと関連付けられていない場合、次の手順を実行する:
  1. そのテキストトラックに関連付けられている SourceBufferactiveSourceBuffers から削除する。
  2. タスクをキューして、 イベントを発火し、 名前が removesourcebuffer のイベントを activeSourceBuffers で発火する。
テキストトラックの mode"showing" または "hidden" になり、そのトラックに関連付けられている SourceBuffer が、 まだ activeSourceBuffers に含まれていない場合、次の手順を実行する:
  1. そのテキストトラックに関連付けられている SourceBufferactiveSourceBuffers に追加する。
  2. タスクをキューして、 イベントを発火し、 名前が addsourcebuffer のイベントを activeSourceBuffers で発火する。

3.15.6 duration変更

durationnew duration に変更する必要がある場合、以下の手順に従います。

  1. 現在の duration の値が new duration と等しい場合、戻ります。
  2. new duration が、 SourceBuffersourceBuffers内)のすべてにわたる バッファ済み coded frames の最大の presentation timestamp より小さい場合、 InvalidStateError 例外を投げて、 これらの手順を中止します。

    現在バッファされているメディアを切り捨てるような duration の短縮は許可されません。 切り捨てが必要な場合は、remove() を使用して duration を更新する前にバッファ範囲を縮小してください。

  3. highest end time を、 すべての SourceBuffersourceBuffers内)の track buffers にわたる track buffer ranges の最大の終了時刻とします。
  4. new durationhighest end time より小さい場合

    この条件は、coded frame removal アルゴリズムが、 削除範囲の開始前に始まる coded frames を保持するために発生することがあります。

    1. new durationhighest end time と等しく更新します。
  5. durationnew duration に更新します。
  6. mirror if necessary アルゴリズムを使って、 メディア要素の duration を更新するため、Window で 以下の手順を実行します:
    1. メディア要素の durationnew duration に更新する。
    2. HTMLMediaElement duration change algorithm を実行する。

3.15.7 ストリーム終了

このアルゴリズムは、アプリケーションが endOfStream() を呼び出してストリームの終了を通知したとき、 またはアルゴリズムがデコードエラーを通知する必要があるときに呼び出されます。 このアルゴリズムは、エラーを通知するかどうかを示す error パラメータを受け取ります。

  1. readyState 属性値を "ended" に変更します。
  2. タスクをキューして、 イベントを発火し、 名前が sourceended のイベントを MediaSource で発火します。
  3. error が設定されていない場合
    1. duration変更 アルゴリズムを、 new duration を すべての SourceBuffersourceBuffers内)の track buffers にわたる track buffer ranges の最大の終了時刻に設定して実行します。

      これにより、durationが追加済みメディアセグメントの終了位置に正しく反映されます。 例えば、durationが明示的に10秒に設定されており、endOfStream()呼び出し前に0~5秒のメディアセグメントだけが追加された場合、 durationは5秒に更新されます。

    2. メディア要素に、すべてのメディアデータが揃ったことを通知します。
    error が "network" に設定されている場合
    mirror if necessary アルゴリズムを使い、 Window で以下の手順を実行します:
    HTMLMediaElementreadyState 属性が HAVE_NOTHING と等しい場合
    resource fetch algorithmmedia data processing steps list にある "If the media data cannot be fetched at all, due to network errors, causing the user agent to give up trying to fetch the resource" の手順を実行します。
    HTMLMediaElementreadyState 属性が HAVE_NOTHING より大きい場合
    "If the connection is interrupted after some media data has been received, causing the user agent to give up trying to fetch the resource" の手順を resource fetch algorithmmedia data processing steps list で実行します。
    error が "decode" に設定されている場合
    mirror if necessary アルゴリズムを使い、 Window で以下の手順を実行します:
    HTMLMediaElementreadyState 属性が HAVE_NOTHING と等しい場合
    "If the media data can be fetched but is found by inspection to be in an unsupported format, or can otherwise not be rendered at all" の手順を resource fetch algorithmmedia data processing steps list で実行します。
    HTMLMediaElementreadyState 属性が HAVE_NOTHING より大きい場合
    media data is corrupted の手順を resource fetch algorithmmedia data processing steps list で実行します。

3.15.8 必要ならmirror

このアルゴリズムは、MediaSource が 同じ Window でアタッチされている場合や DedicatedWorkerGlobalScope からアタッチされている場合に、 Window で手順を実行するために使います。 通常は、アタッチされている HTMLMediaElement の状態を更新するためです。 このアルゴリズムは、steps パラメータ(Window で実行する手順のリスト)を受け取ります。

MediaSourceDedicatedWorkerGlobalScope で構築されている場合:
[[port to main]] に内部 mirror on window メッセージをポストし、 Window の暗黙ハンドラが steps を実行します。 このハンドラの受信を待たずに呼び出し元に制御を返します。
mirrorメッセージ機構の目的は以下の通りです:
  1. stepsWindow 上で 非同期に独立したタスクとして実行されること(他の Window タスクの途中で 実行されるのではなく)、かつ
  2. stepsDedicatedWorkerGlobalScope 上で このアルゴリズムの同期実行やリターンをブロックしないこと
それ以外の場合:
steps を実行する。

4. MediaSourceHandle インターフェース

MediaSourceHandle インターフェースは、 MediaSource オブジェクトのプロキシを表します。 これは、DedicatedWorkerGlobalScopeMediaSourceWindowHTMLMediaElementsrcObject を使って アタッチする際に便利です(メディア要素へのアタッチアルゴリズム参照)。

この別オブジェクトは、クロスコンテキストの MediaSource を メディア要素にアタッチするために必要です。なぜなら MediaSource オブジェクト自体は イベントターゲットであるため、transferableではありません。

それぞれの MediaSourceHandle オブジェクトは [[has ever been assigned as srcobject]] という内部スロットを持ちます。 これは boolean 型で、 MediaSourceHandle オブジェクト生成時は false で初期化されます。 HTMLMediaElementsrcObject セッター( 10. HTMLMediaElement拡張参照)で true に設定されます。 true の場合は MediaSourceHandle の 転送が成功しなくなります(4.1 転送参照)。

MediaSourceHandle オブジェクトは Transferable であり、それぞれ [[Detached]] という内部スロットを持ちます。これは、一度転送されたハンドルオブジェクトインスタンスが、再度転送できないことを保証するために使われます。

WebIDL[Transferable, Exposed=(Window,DedicatedWorker)]
interface MediaSourceHandle {};

4.1 転送

MediaSourceHandle転送手順転送受信手順 では、 実装が基礎となる MediaSource への暗黙内部スロット参照を維持する必要があります。 これは メディア要素へのアタッチアルゴリズムで srcObject を使ったアタッチや、 その後の クロスコンテキスト通信モデルのセットアップを可能にするためです。

実装者は、Transferable によって 暗黙的に「ムーブ」セマンティクスが想定されがちですが、常に現実とは限らないことに注意すべきです。 例えば、postMessageの拡張や内部実装がブロードキャスト方式になっている場合、 転送された MediaSourceHandle の 受信側が複数になりえることがあります。 そのため、実装は、基礎となる MediaSourceHandle のいずれのハンドルが アタッチに有効かを、メディア要素のリソース選択アルゴリズムの非同期部分でハンドルが使われるまで決定しないことが推奨されます。 これは、容易にクローン可能な MediaSourceオブジェクトURLによるアタッチと類似しており、 そのURLは(多数のクローンがあっても)1度だけアタッチの開始に有効です。

実装は、基礎となる MediaSource オブジェクトに対して srcObject による アタッチ(ロード)を MUST 最大1回のみサポートする必要があります。 これは MediaSourceHandleTransferable 実装の違いによるクローンの有無を問わずです。

これが非同期部分でどのように強制されるかは メディア要素へのアタッチを参照してください。

MediaSourceHandleWindowDedicatedWorkerGlobalScope コンテキストでのみ公開され、異なる agent cluster [ECMASCRIPT] 間の転送は成功しません。 MediaSourceHandle オブジェクトの転送は、 同じ agent cluster 内でのみ成功します。

例えば、MediaSourceHandle オブジェクトを WindowDedicatedWorkerGlobalScope から SharedWorker や ServiceWorker に転送しても成功しません。 開発者は、MediaSourceオブジェクトURL のような DOMString は 多様な方法で通信できることとの違いに注意が必要です。 それでも メディア要素へのアタッチMediaSourceオブジェクトURL を使う場合、 MediaSourceWindow コンテキストで構築されたときのみ成功します。 関連する agentagent cluster の WebアプリAPIへの統合(dedicated worker agents など)については [HTML] も参照してください。

転送手順 では、 MediaSourceHandle オブジェクトに対して 以下の手順を MUST 含めなければなりません:

  1. MediaSourceHandle[[has ever been assigned as srcobject]] 内部スロットが true の場合は、 転送手順DataCloneError 例外を投げて失敗しなければなりません。

5. SourceBuffer インターフェース

WebIDLenum AppendMode {
  "segments",
  "sequence",
};
segments
メディアセグメント内のタイムスタンプによって、符号化フレームがプレゼンテーション内のどこに配置されるかが決定されます。メディアセグメントはどの順序でも追加できます。
sequence
メディアセグメントは、セグメント内のタイムスタンプに関係なく時間的に隣接して扱われます。新しいメディアセグメント内の符号化フレームは、直前のメディアセグメント内の符号化フレームの直後に配置されます。新しいオフセットが必要な場合、timestampOffset属性が更新され、メディアセグメント同士を隣接させます。"sequence"モードでtimestampOffset属性を設定すると、メディアセグメント内のタイムスタンプを知らなくてもタイムライン上の特定位置に配置できます。
WebIDL[Exposed=(Window,DedicatedWorker)]
interface SourceBuffer : EventTarget { ... };
Issue 280: MSE-in-Workers: {Audio,Video,Text}Track{,List} IDL in HTML need additional DedicatedWorker in Exposed mse-in-workers
[HTML] AudioTrackList, VideoTrackList および TextTrackList に Window+DedicatedWorker での公開が必要です。

5.1 属性

modeAppendMode

一連のメディアセグメントをどのように扱うか制御します。この属性は、オブジェクト生成後にaddSourceBuffer()によって最初に設定され、changeType()またはこの属性の設定で変更できます。

取得時は、初期値または最後に正常に設定された値を返します。

設定時は、以下の手順を実行します:

  1. このオブジェクトがsourceBuffers属性から削除されている場合は、InvalidStateError例外を投げて手順を中止します。
  2. updating属性がtrueの場合は、InvalidStateError例外を投げて手順を中止します。
  3. new mode を、新しく設定される値とします。
  4. [[generate timestamps flag]] がtrueで、new modeが"segments"の場合、TypeError例外を投げて手順を中止します。
  5. readyState属性が parent media source の "ended"状態の場合、以下の手順を実行します:

    1. readyState属性を "open"に設定する
    2. タスクをキューして、 イベントを発火し、 名前がsourceopenのイベントを parent media sourceで発火する
  6. [[append state]]PARSING_MEDIA_SEGMENTの場合、InvalidStateErrorを投げて手順を中止する。
  7. new modeが"sequence"なら、[[group start timestamp]][[group end timestamp]]で更新する。
  8. 属性をnew modeへ更新する。
updatingboolean(readonly)

appendBuffer()remove()の非同期処理が継続中かどうかを示します。この属性は、オブジェクト生成時はfalseで初期化されます。

bufferedTimeRanges(readonly)

このSourceBufferにバッファされているTimeRangesを示します。この属性は、オブジェクト生成時に空のTimeRangesオブジェクトで初期化されます。

属性の読み出し時は、以下の手順をMUST実行します:

  1. このオブジェクトがsourceBuffers属性から削除されている場合は、InvalidStateError例外を投げて中止。
  2. highest end time を、このSourceBufferが管理するすべてのtrack buffersにわたるtrack buffer rangesの最大終了時刻とする。
  3. intersection ranges を、0からhighest end timeまでの単一範囲を持つTimeRangesオブジェクトとする。
  4. このSourceBufferが管理する各オーディオ・ビデオtrack bufferについて、以下の手順を行う:

    テキストtrack bufferは上記highest end timeの計算には含まれるが、ここでのバッファ範囲計算からは除外される。テキストトラックは必ずしも連続しておらず、他メディアトラックが同一時間範囲で連続している場合に、テキストトラック内の不連続性で再生が停止するべきではない。

    1. track ranges を、現在のtrack buffertrack buffer rangesとする。
    2. readyStateが"ended"なら、track rangesの最後の範囲の終了時刻をhighest end timeに設定する。
    3. new intersection ranges を、intersection rangestrack rangesの積集合とする。
    4. intersection rangesの範囲をnew intersection rangesで置き換える。
  5. intersection rangesが現在の属性値と異なる場合、属性値をintersection rangesに更新する。
  6. 現在の属性値を返す。
timestampOffsetdouble

このSourceBufferへ追加される以降のメディアセグメント内のタイムスタンプに適用されるオフセットを制御します。timestampOffsetは初期値0(オフセットなし)で設定されます。

取得時は、初期値または最後に正常に設定された値を返します。

設定時は以下の手順を実行します:

  1. new timestamp offset を新しく設定する値とする。
  2. このオブジェクトがsourceBuffers属性から削除されている場合は、InvalidStateError例外を投げて手順を中止。
  3. updating属性がtrueの場合は、InvalidStateError例外を投げて手順を中止。
  4. readyState属性が parent media source の "ended"状態の場合、以下の手順を実行:

    1. readyState属性を "open"に設定する
    2. タスクをキューして、 イベントを発火し、 名前がsourceopenのイベントを parent media sourceで発火する
  5. [[append state]]PARSING_MEDIA_SEGMENTの場合、InvalidStateErrorを投げて中止。
  6. mode属性が"sequence"の場合、[[group start timestamp]]new timestamp offsetで設定する。
  7. 属性値をnew timestamp offsetへ更新する。
audioTracksAudioTrackList(readonly)
このオブジェクトによって生成されたAudioTrackオブジェクトのリスト。
videoTracksVideoTrackList(readonly)
このオブジェクトによって生成されたVideoTrackオブジェクトのリスト。
textTracksTextTrackList(readonly)
このオブジェクトによって生成されたTextTrackオブジェクトのリスト。
appendWindowStartdouble

append windowの開始位置となるpresentation timestamp。初期値はpresentation start time

取得時は、初期値または最後に正常に設定された値を返します。

設定時は以下の手順を実行します:

  1. このオブジェクトがsourceBuffers属性から削除されている場合、InvalidStateError例外を投げて中止。
  2. updating属性がtrueの場合、InvalidStateError例外を投げて中止。
  3. 新しい値が0未満、またはappendWindowEnd以上の場合、TypeError例外を投げて中止。
  4. 属性値を新しい値へ更新。
appendWindowEndunrestricted double

append windowの終了位置となるpresentation timestamp。初期値は正のInfinity。

取得時は、初期値または最後に正常に設定された値を返します。

設定時は以下の手順を実行します:

  1. このオブジェクトがsourceBuffers属性から削除されている場合 InvalidStateError例外を投げて中止。
  2. updating属性がtrueの場合、InvalidStateError例外を投げて中止。
  3. 新しい値がNaNの場合、TypeError例外を投げて中止。
  4. 新しい値がappendWindowStart以下の場合、TypeError例外を投げて中止。
  5. 属性値を新しい値へ更新。
onupdatestartEventHandler

updatestartイベントのイベントハンドラ。

onupdateEventHandler

updateイベントのイベントハンドラ。

onupdateendEventHandler

updateendイベントのイベントハンドラ。

onerrorEventHandler

errorイベントのイベントハンドラ。

onabortEventHandler

abortイベントのイベントハンドラ。

5.2 メソッド

appendBuffer

BufferSource[WEBIDL] のセグメントデータを SourceBufferに追加します。

このメソッドが呼び出されると、ユーザーエージェントは次の手順を実行します:

  1. prepare append アルゴリズムを実行する。
  2. data[[input buffer]] の末尾に追加する。
  3. updating 属性を true に設定する。
  4. タスクをキューして、 イベントを発火し、 名前が updatestart のイベントをこの SourceBufferオブジェクトで発火する。
  5. 非同期で buffer append アルゴリズムを実行する。
abort

現在のセグメントを中止し、セグメントパーサーをリセットします。

このメソッドが呼び出されると、ユーザーエージェントは次の手順を実行します:

  1. このオブジェクトが sourceBuffers 属性から削除されている場合は、 parent media source に対して InvalidStateError 例外を投げて、手順を中止する。
  2. readyState 属性が parent media source で "open" でない場合は InvalidStateError 例外を投げて、中止する。
  3. range removal アルゴリズムが実行中の場合、InvalidStateError例外を投げて中止する。
  4. updating 属性が true の場合、次を実行:
    1. buffer appendアルゴリズムが実行中なら中止する。
    2. updating属性をfalseに設定。
    3. タスクをキューして、 イベントを発火し、 名前がabortのイベントをこの SourceBufferで発火。
    4. タスクをキューして、 イベントを発火し、 名前がupdateendのイベントをこの SourceBufferで発火。
  5. reset parser stateアルゴリズムを実行。
  6. appendWindowStartpresentation start timeに設定。
  7. appendWindowEndを正のInfinityに設定。
changeType

このオブジェクトに関連付けられたMIMEタイプを変更します。以降の appendBuffer() 呼び出しでは、新しい型に準拠したバイト列が期待されます。

このメソッドが呼び出されると、ユーザーエージェントは次の手順を実行します:

  1. type が空文字列なら TypeError例外を投げて中止。
  2. このオブジェクトが sourceBuffers 属性から削除されている場合は parent media source に対して InvalidStateError例外を投げて中止。
  3. updating属性がtrueの場合は、InvalidStateError例外を投げて中止。
  4. type がサポートされないMIMEタイプ、または SourceBufferオブジェクトの sourceBuffers属性で(現在または過去に)指定された型と互換性がないMIMEタイプを含む場合、 parent media source に対して NotSupportedError例外を投げて中止。
  5. readyState属性が parent media source の "ended"状態の場合、以下の手順を実行:

    1. readyState属性を "open"に設定。
    2. タスクをキューして イベントを発火し、 名前がsourceopenのイベントを parent media sourceで発火。
  6. reset parser stateアルゴリズムを実行。
  7. このSourceBuffer[[generate timestamps flag]]を byte stream format registry [MSE-REGISTRY]の typeに対応する「Generate Timestamps Flag」カラムの値で更新する。
  8. [[generate timestamps flag]]がtrueの場合:
    このmode属性を "sequence"にし、関連する属性設定手順も実行する。
    それ以外の場合:
    このmode属性の以前の値を保持し、 属性設定時の手順は実行しない。
  9. このSourceBuffer[[pending initialization segment for changeType flag]]をtrueに設定。
remove

指定した時間範囲のメディアを削除します。削除範囲のstart(秒)はpresentation start timeからの秒数です。end(秒)もpresentation start timeからの秒数です。

このメソッドが呼び出されると、ユーザーエージェントは次の手順を実行します:

  1. このオブジェクトが sourceBuffers 属性から削除されている場合は parent media source に対して InvalidStateError例外を投げて中止。
  2. updating属性がtrueの場合は、InvalidStateError例外を投げて中止。
  3. durationがNaNなら、TypeError例外を投げて中止。
  4. startが負またはdurationより大きい場合、 TypeError例外を投げて中止。
  5. endstart以下、またはNaNの場合、 TypeError例外を投げて中止。
  6. readyState属性が parent media source の "ended"状態の場合、以下の手順を実行:

    1. readyState属性を "open"に設定。
    2. タスクをキューして イベントを発火し、 名前がsourceopenのイベントを parent media sourceで発火。
  7. range removalアルゴリズムを、startendを削除範囲の開始・終了として実行。

5.3 トラックバッファ

track buffer は、個々のトラックの track descriptionscoded frames を保存します。track bufferは、initialization segmentsmedia segmentsSourceBufferに追加されるたびに更新されます。

track bufferは、last decode timestamp という変数を持ち、現在のcoded frame groupで最後に追加されたcoded frameのdecode timestampを保存します。初期状態は未設定で、まだフレームが追加されていないことを示します。

track bufferは、last frame duration という変数を持ち、現在のcoded frame groupで最後に追加されたcoded frame durationを保存します。初期状態は未設定。

track bufferは、highest end timestamp という変数を持ち、現在のcoded frame groupでこのtrack bufferに追加された全coded frame end timestampのうち最大値を保存します。初期状態は未設定。

track bufferは、need random access point flag という変数を持ち、track bufferがrandom access pointcoded frameを待っているかどうかを記録します。初期値はtrueで、何かを追加するにはまずrandom access pointcoded frameが必要であることを示します。

track bufferは、track buffer ranges という変数を持ち、track bufferに現在保存されているcoded framesが占めるプレゼンテーション時間範囲を表します。

track buffer rangesについては、これらのプレゼンテーション時間範囲はpresentation timestamps、フレーム持続時間、およびmuxedSourceBuffer内のtrack bufferをまたぐcoded frame groupの開始時刻などに基づきます。

仕様上は、この情報はnormalized TimeRanges objectとして保存されているものとみなします。交差したtrack buffer rangesHTMLMediaElementbufferedの レポートに使われ、MUSTその範囲内で途切れなく再生できる必要があります。

これらのcoded frame groupの開始時刻は、coded frame processingアルゴリズムで言及されるものとは若干異なり、 すべてのtrack bufferをまたいだ不連続後の最も早いpresentation timestampとなります。不連続は coded frame processingアルゴリズム内でも発生し得ますし、 coded frame removalアルゴリズムの結果でも発生し得ます(modeによらず)。track buffer rangesの分離判定閾値は実装依存です。例えば、予期しない再生停止を減らすため、実装は coded frame processingアルゴリズムの不連続検出ロジックを近似し、 このtrack bufferでこれまでバッファされた最大フレーム持続時間の2倍未満の隙間で隣接範囲を統合するMAYです。 実装はまた、muxedSourceBuffer内で coded frame groupの開始時刻を範囲の開始に使い、予期しない再生停止をさらに減らすMAYです。

5.4 イベント概要

イベント名 インターフェース 発生タイミング
updatestart Event SourceBufferupdating が false から true に遷移したとき。
update Event SourceBuffer への追加または削除が正常終了したとき。SourceBufferupdating が true から false に遷移したとき。
updateend Event SourceBuffer への追加または削除が終了したとき。
error Event SourceBuffer への追加中にエラーが発生したとき。updating が true から false に遷移したとき。
abort Event SourceBuffer への追加が abort() の呼び出しで中断されたとき。updating が true から false に遷移したとき。

5.5 アルゴリズム

5.5.1 セグメントパーサーループ

SourceBuffer オブジェクトは、セグメントパースの高レベル状態を追跡するための [[append state]] 内部スロットを持ちます。初期値は WAITING_FOR_SEGMENT であり、データ追加時に以下の状態に遷移します。

追加状態名 説明
WAITING_FOR_SEGMENT initialization segment または media segment の開始を待っている状態。
PARSING_INIT_SEGMENT 現在、initialization segment をパースしている状態。
PARSING_MEDIA_SEGMENT 現在、media segment をパースしている状態。

SourceBuffer オブジェクトは [[input buffer]] 内部スロットを持ち、これは appendBuffer() の呼び出し間で未パースのバイト列を保持するバイトバッファです。SourceBufferオブジェクト生成時は空です。

SourceBuffer オブジェクトは [[buffer full flag]] 内部スロットを持ち、これは appendBuffer() で追加可能なバイト数の上限に達しているかどうかを追跡します。オブジェクト生成時は false で、データ追加や削除により更新されます。

SourceBuffer オブジェクトは [[group start timestamp]] 内部スロットを持ち、"sequence" モードで新しい coded frame group の開始タイムスタンプを記録します。オブジェクト生成時は未設定であり、mode 属性が "sequence" かつ timestampOffset 属性が設定されたとき、または coded frame processing アルゴリズム実行時に更新されます。

SourceBuffer オブジェクトは [[group end timestamp]] 内部スロットを持ち、現在の coded frame group 全体の coded frame end timestamp の最大値を保存します。オブジェクト生成時は 0 で、coded frame processing アルゴリズムで更新されます。

[[group end timestamp]] は、SourceBuffer 内の全 track bufferscoded frame end timestamp の最大値を記録します。複数トラックでタイムスタンプが揃っていない多重化セグメント追加時は、mode 属性の設定に注意してください。

SourceBuffer オブジェクトは [[generate timestamps flag]] 内部スロット(boolean型)を持ち、coded frames に対してタイムスタンプ生成が必要かどうかを追跡します。このフラグは、addSourceBuffer()でオブジェクト生成時に設定され、changeType()で更新されます。

セグメントパーサーループアルゴリズムが呼び出されたとき、次の手順を実行します:

  1. ループトップ: [[input buffer]] が空なら、下記 need more data 手順にジャンプする。
  2. [[input buffer]] のバイト列が SourceBufferバイトストリームフォーマット仕様に違反している場合、append error アルゴリズムを実行し、このアルゴリズムを中止する。
  3. byte stream format specifications で無視すべきとされているバイトを [[input buffer]] の先頭から除去する。
  4. [[append state]]WAITING_FOR_SEGMENT の場合、以下の手順を実行:

    1. [[input buffer]] の先頭が initialization segment の開始を示している場合、[[append state]]PARSING_INIT_SEGMENT に設定する。
    2. [[input buffer]] の先頭が media segment の開始を示している場合、[[append state]]PARSING_MEDIA_SEGMENT に設定する。
    3. 上記 ループトップ 手順にジャンプする。
  5. [[append state]]PARSING_INIT_SEGMENT の場合、以下の手順を実行:

    1. [[input buffer]] が完全な initialization segment をまだ含んでいなければ、下記 need more data 手順にジャンプする。
    2. initialization segment received アルゴリズムを実行する。
    3. initialization segment のバイトを [[input buffer]] の先頭から削除する。
    4. [[append state]]WAITING_FOR_SEGMENT に設定する。
    5. 上記 ループトップ 手順にジャンプする。
  6. [[append state]]PARSING_MEDIA_SEGMENT の場合、以下の手順を実行:

    1. [[first initialization segment received flag]] が false または [[pending initialization segment for changeType flag]] が true の場合、append errorアルゴリズムを実行し、このアルゴリズムを中止する。
    2. [[input buffer]] が一つ以上の完全な coded frames を含む場合、coded frame processing アルゴリズムを実行する。

      coded frame processing アルゴリズムの実行頻度は実装依存です。input bufferに完全なメディアセグメントがあるとき、または完全な coded frames が追加されるたびに複数回呼ぶMAYです。

    3. この SourceBuffer が一杯でさらにメディアデータを受け付けられない場合、[[buffer full flag]] を true に設定する。
    4. [[input buffer]] が完全な media segment を含まない場合、下記 need more data 手順にジャンプする。
    5. media segment のバイトを [[input buffer]] の先頭から削除する。
    6. [[append state]]WAITING_FOR_SEGMENT に設定する。
    7. 上記 ループトップ 手順にジャンプする。
  7. need more data: 呼び出し元アルゴリズムへ制御を返す。

5.5.2 パーサ状態のリセット

パーサ状態をリセットする必要がある場合、以下の手順を実行します:

  1. [[append state]]PARSING_MEDIA_SEGMENT で、 [[input buffer]] にいくつかの完全な coded frames が含まれている場合は、 それらの完全な coded frames がすべて処理されるまで coded frame processing アルゴリズムを実行する。
  2. すべての track bufferslast decode timestamp を未設定にする。
  3. すべての track bufferslast frame duration を未設定にする。
  4. すべての track buffershighest end timestamp を未設定にする。
  5. すべての track buffersneed random access point flag を true に設定する。
  6. mode 属性が "sequence" の場合、 [[group start timestamp]][[group end timestamp]] で設定する。
  7. [[input buffer]] の全てのバイトを削除する。
  8. [[append state]]WAITING_FOR_SEGMENT に設定する。

5.5.3 追加エラー

追加操作中にエラーが発生した時に呼ばれるアルゴリズムです。

  1. reset parser state アルゴリズムを実行する。
  2. updating 属性を false に設定する。
  3. タスクをキューして イベントを発火し 名前が error のイベントをこの SourceBuffer オブジェクトで発火する。
  4. タスクをキューして イベントを発火し 名前が updateend のイベントをこの SourceBuffer オブジェクトで発火する。
  5. end of stream アルゴリズムを error パラメータを "decode" にして実行する。

5.5.4 追加準備

追加操作が開始されると、SourceBuffer の検証および準備のために以下の手順を実行します。

  1. SourceBuffersourceBuffers 属性から削除されている場合は parent media source に対して InvalidStateError 例外を投げて中止。
  2. updating 属性が true の場合は InvalidStateError 例外を投げて中止。
  3. recent element error を次のように判定する:
    MediaSourceWindow で構築されている場合
    HTMLMediaElementerror 属性が null でなければ true。null なら false。
    それ以外の場合
    WindowHTMLMediaElementerror 属性が変更された時、[[port to worker]] の暗黙メッセージで通知された値とする。まだメッセージが受信されていなければ false。
  4. recent element error が true の場合、InvalidStateError 例外を投げて中止。
  5. readyState 属性が parent media source で "ended" の場合、以下の手順を実行:

    1. readyState 属性を parent media source で "open" に設定する
    2. タスクをキューして イベントを発火し 名前が sourceopen のイベントを parent media source で発火する。
  6. coded frame eviction アルゴリズムを実行する。
  7. [[buffer full flag]] が true の場合は QuotaExceededError 例外を投げて中止。

    これは、追加に必要な十分なデータの削除ができなかった、もしくは追加サイズが大きすぎることを示します。ウェブアプリケーションは remove() を使って明示的に空き領域を確保するか、追加サイズを減らすべきです。

5.5.5 バッファ追加

appendBuffer() が呼び出された際、追加されたデータの処理に以下の手順を実行します。

  1. segment parser loop アルゴリズムを実行する。
  2. 前の手順で segment parser loop アルゴリズムが中止された場合は、このアルゴリズムを中止する。
  3. updating 属性を false に設定する。
  4. タスクをキューして イベントを発火し 名前が update のイベントをこの SourceBuffer オブジェクトで発火する。
  5. タスクをキューして イベントを発火し 名前が updateend のイベントをこの SourceBuffer オブジェクトで発火する。

5.5.6 範囲削除

JavaScript から見える範囲削除操作を開始し、他の SourceBuffer の更新をブロックする必要がある場合は以下の手順に従います:

  1. start を、削除範囲の開始 presentation timestamp(秒、presentation start timeからの秒数)とする。
  2. end を、削除範囲の終了 presentation timestamp(秒、presentation start timeからの秒数)とする。
  3. updating 属性を true に設定する。
  4. タスクをキューして イベントを発火し 名前が updatestart のイベントをこの SourceBuffer オブジェクトで発火する。
  5. 呼び出し元に制御を返し、残りの手順は非同期で実行する。
  6. coded frame removal アルゴリズムを start および end を削除範囲として実行する。
  7. updating 属性を false に設定する。
  8. タスクをキューして イベントを発火し 名前が update のイベントをこの SourceBuffer オブジェクトで発火する。
  9. タスクをキューして イベントを発火し 名前が updateend のイベントをこの SourceBuffer オブジェクトで発火する。

5.5.7 initialization セグメント受信

segment parser loop が完全な initialization segment を正常にパースしたとき、次の手順を実行します。

各 SourceBuffer オブジェクトは、最初の initialization segment がこのアルゴリズムによって追加・受信されたかどうかを追跡する [[first initialization segment received flag]] 内部スロットを持ちます。このフラグは SourceBuffer 作成時に false に設定され、以下のアルゴリズムで更新されます。

各 SourceBuffer オブジェクトは、直近の changeType() 以降に initialization segment が必要かどうかを追跡する [[pending initialization segment for changeType flag]] 内部スロットを持ちます。このフラグは SourceBuffer 作成時に false に設定され、 changeType() により true に設定され、 以下のアルゴリズムにより false に戻されます。

  1. 現在の duration 属性が NaN に等しい場合は更新する:
    initialization segment に duration が含まれている場合:
    duration 変更 アルゴリズムを、 new duration を initialization segment 内の duration に設定して実行する。
    それ以外の場合:
    duration 変更 アルゴリズムを、 new duration を正の Infinity に設定して実行する。
  2. initialization segment に音声・動画・テキストのいずれのトラックも含まれていない場合、 append error アルゴリズムを実行して、これらの手順を中止する。
  3. [[first initialization segment received flag]] が true の場合、次の手順を実行する:
    1. 以下の性質を検証する。いずれかの検証に失敗した場合は append error アルゴリズムを実行して、これらの手順を中止する。
      • 音声・動画・テキストトラックの数が最初の initialization segment のものと一致している。
      • ある種類に複数トラックが存在する場合(例:音声トラックが 2 本)、 各トラックの Track ID が最初の initialization segment のものと一致している。
      • 各トラックのコーデックがユーザーエージェントでサポートされている。

        ユーザーエージェントは、通常はサポートされるコーデックであっても、ここでは MAY 「サポートされない」と見なすことがあります。例えば、そのコーデックが type パラメータとして (a) この SourceBuffer オブジェクトに対して直近で成功した changeType() の呼び出し、または (b) まだ成功した changeType() がない場合は、当該オブジェクトを作成した addSourceBuffer() において、正確に指定されていないときです。例えば、直近で成功した changeType()'video/webm' または 'video/webm; codecs="vp8"' で呼び出されており、initialization segment に vp9 のビデオトラックが現れた場合、 他の 2 つの性質の検証が通っていても、この手順を用いてデコードエラーをトリガーすることが MAY です。実装は、コーデックが実際にサポートされていない場合や他の 2 つの検証が失敗する場合にのみエラーをトリガーすることが推奨されます。 Web 作者は、ユーザーエージェントのサポートをより積極的に検出するため、 changeType()addSourceBuffer()、 および isTypeSupported() を正確なコーデックパラメータで使用することが推奨されます。さらに、 changeType() は、SourceBuffer オブジェクトの bytestream 形式が変わる場合に必要です。

    2. この initialization segment から適切な track descriptions を各 track buffers に追加する。
    3. すべての track buffer の need random access point flag を true に設定する。
  4. active track flag を false とする。
  5. [[first initialization segment received flag]] が false の場合、次の手順を実行する:

    1. initialization segment に、ユーザーエージェントがサポートしないコーデックのトラックが含まれている場合、 append error アルゴリズムを実行して中止する。

      ユーザーエージェントは、通常はサポートされるコーデックでも、ここでは「サポートされない」と MAY 見なすことがあります。これは、そのコーデックが type パラメータとして (a) この SourceBuffer オブジェクトに対して直近で成功した changeType() の呼び出し、または (b) 当該オブジェクトでまだ成功した changeType() が無い場合は、当該オブジェクトを作成した addSourceBuffer() において正確に指定されていないときです。例えば、 MediaSource.isTypeSupported('video/webm;codecs="vp8,vorbis"') が true を返す場合でも、 addSourceBuffer()'video/webm;codecs="vp8"' で呼ばれ、initialization segment に Vorbis トラックが現れたなら、 この手順を用いてデコードエラーをトリガーすることが MAY です。実装は、コーデックが実際に非サポートの場合にのみエラーをトリガーすることが推奨されます。 Web 作者は、より積極的にユーザーエージェントのサポートを検出するため、 changeType()addSourceBuffer()、 および isTypeSupported() を正確なコーデックパラメータで用いることが推奨されます。 また、changeType() は、SourceBuffer オブジェクトの bytestream 形式が変更される場合に必要です。

    2. initialization segment の各音声トラックについて、次の手順を実行する:

      1. audio byte stream track ID を、処理中の現在のトラックの Track ID とする。
      2. audio language を、このトラックについて initialization segment で指定された言語の BCP 47 言語タグ、 または言語情報が無い場合は空文字列とする。
      3. audio language が BCP 47 の 'und' に等しい場合、 audio language に空文字列を代入する。
      4. audio label を、このトラックについて initialization segment で指定されたラベル、 または情報が無い場合は空文字列とする。
      5. audio kinds を、このトラックについて initialization segment で指定された kind 文字列のシーケンス、 あるいは情報が無い場合は空文字列 1 要素のシーケンスとする。
      6. audio kinds の各値について、次の手順を実行する:
        1. current audio kind を、この反復における audio kinds の値とする。
        2. new audio track を新しい AudioTrack オブジェクトとする。
        3. ユニークな ID を生成し、new audio trackid プロパティに代入する。
        4. audio languagenew audio tracklanguage プロパティに代入する。
        5. audio labelnew audio tracklabel プロパティに代入する。
        6. current audio kindnew audio trackkind プロパティに代入する。
        7. この SourceBuffer オブジェクトの audioTrackslength が 0 に等しい場合、次を実行する:

          1. new audio trackenabled プロパティを true に設定する。
          2. active track flag を true に設定する。
        8. new audio track を、この audioTracks 属性に追加する(対象はこの SourceBuffer オブジェクト)。

          これにより、 AudioTrackList [HTML] のロジックが作動し、 タスクをキューして イベントを発火し、 addtrack という名前のイベントを、TrackEvent を用い、 その track 属性を new audio track に初期化して、 この audioTracks 属性が参照する AudioTrackList オブジェクトで発火させるはずです。

        9. parent media sourceDedicatedWorkerGlobalScope で構築されている場合:
          内部の create track mirror メッセージを [[port to main]] にポストし、Window の暗黙ハンドラが次の手順を実行する:
          1. mirrored audio track を新しい AudioTrack オブジェクトとする。
          2. mirrored audio track に、 new audio track と同一のプロパティ値を設定する。
          3. mirrored audio track を HTMLMediaElement の audioTracks 属性に追加する。
          それ以外の場合:
          new audio track を HTMLMediaElement の audioTracks 属性に追加する。

          これにより、 AudioTrackList [HTML] のロジックが作動し、 タスクをキューして イベントを発火し、 addtrack という名前のイベントを、TrackEvent を用い、 その track 属性を mirrored audio track または new audio track に初期化して、 HTMLMediaElement の audioTracks 属性が参照する AudioTrackList オブジェクトで発火させるはずです。

      7. このトラックの coded frames を格納するための新しい track buffer を作成する。
      8. このトラックの track descriptiontrack buffer に追加する。
    3. initialization segment の各動画トラックについて、次の手順を実行する:

      1. video byte stream track ID を、処理中の現在のトラックの Track ID とする。
      2. video language を、このトラックについて initialization segment で指定された言語の BCP 47 言語タグ、 または言語情報が無い場合は空文字列とする。
      3. video language が BCP 47 の 'und' に等しい場合、 video language に空文字列を代入する。
      4. video label を、このトラックについて initialization segment で指定されたラベル、 または情報が無い場合は空文字列とする。
      5. video kinds を、このトラックについて initialization segment で指定された kind 文字列のシーケンス、 あるいは情報が無い場合は空文字列 1 要素のシーケンスとする。
      6. video kinds の各値について、次の手順を実行する:
        1. current video kind を、この反復における video kinds の値とする。
        2. new video track を新しい VideoTrack オブジェクトとする。
        3. ユニークな ID を生成し、new video trackid プロパティに代入する。
        4. video languagenew video tracklanguage プロパティに代入する。
        5. video labelnew video tracklabel プロパティに代入する。
        6. current video kindnew video trackkind プロパティに代入する。
        7. この SourceBuffer オブジェクトの videoTrackslength が 0 に等しい場合、次を実行する:

          1. new video trackselected プロパティを true に設定する。
          2. active track flag を true に設定する。
        8. new video track を、この videoTracks 属性に追加する(対象はこの SourceBuffer オブジェクト)。

          これにより、 VideoTrackList [HTML] のロジックが作動し、 タスクをキューして イベントを発火し、 addtrack という名前のイベントを、TrackEvent を用い、 その track 属性を new video track に初期化して、 この videoTracks 属性が参照する VideoTrackList オブジェクトで発火させるはずです。

        9. parent media sourceDedicatedWorkerGlobalScope で構築されている場合:
          内部の create track mirror メッセージを [[port to main]] にポストし、Window の暗黙ハンドラが次の手順を実行する:
          1. mirrored video track を新しい VideoTrack オブジェクトとする。
          2. mirrored video track に、 new video track と同一のプロパティ値を設定する。
          3. mirrored video track を HTMLMediaElement の videoTracks 属性に追加する。
          それ以外の場合:
          new video track を HTMLMediaElement の videoTracks 属性に追加する。

          これにより、 VideoTrackList [HTML] のロジックが作動し、 タスクをキューして イベントを発火し、 addtrack という名前のイベントを、TrackEvent を用い、 その track 属性を mirrored video track または new video track に初期化して、 HTMLMediaElement の videoTracks 属性が参照する VideoTrackList オブジェクトで発火させるはずです。

      7. このトラックの coded frames を格納するための新しい track buffer を作成する。
      8. このトラックの track descriptiontrack buffer に追加する。
    4. initialization segment の各テキストトラックについて、次の手順を実行する:

      1. text byte stream track ID を、処理中の現在のトラックの Track ID とする。
      2. text language を、このトラックについて initialization segment で指定された言語の BCP 47 言語タグ、 または言語情報が無い場合は空文字列とする。
      3. text language が BCP 47 の 'und' に等しい場合、 text language に空文字列を代入する。
      4. text label を、このトラックについて initialization segment で指定されたラベル、 または情報が無い場合は空文字列とする。
      5. text kinds を、このトラックについて initialization segment で指定された kind 文字列のシーケンス、 あるいは情報が無い場合は空文字列 1 要素のシーケンスとする。
      6. text kinds の各値について、次の手順を実行する:
        1. current text kind を、この反復における text kinds の値とする。
        2. new text track を新しい TextTrack オブジェクトとする。
        3. ユニークな ID を生成し、new text trackid プロパティに代入する。
        4. text languagenew text tracklanguage プロパティに代入する。
        5. text labelnew text tracklabel プロパティに代入する。
        6. current text kindnew text trackkind プロパティに代入する。
        7. new text track の残りのプロパティを、initialization segment から取得した適切な情報で埋める。
        8. new text trackmode プロパティが "showing" または "hidden" に等しい場合、active track flag を true に設定する。
        9. new text track を、この textTracks 属性に追加する(対象はこの SourceBuffer オブジェクト)。

          これにより、 TextTrackList [HTML] のロジックが作動し、 タスクをキューして イベントを発火し、 addtrack という名前のイベントを、TrackEvent を用い、 その track 属性を new text track に初期化して、 この textTracks 属性が参照する TextTrackList オブジェクトで発火させるはずです。

        10. parent media sourceDedicatedWorkerGlobalScope で構築されている場合:
          内部の create track mirror メッセージを [[port to main]] にポストし、Window の暗黙ハンドラが次の手順を実行する:
          1. mirrored text track を新しい TextTrack オブジェクトとする。
          2. mirrored text track に、 new text track と同一のプロパティ値を設定する。
          3. mirrored text track を HTMLMediaElement の textTracks 属性に追加する。
          それ以外の場合:
          new text track を HTMLMediaElement の textTracks 属性に追加する。

          これにより、 TextTrackList [HTML] のロジックが作動し、 タスクをキューして イベントを発火し、 addtrack という名前のイベントを、TrackEvent を用い、 その track 属性を mirrored text track または new text track に初期化して、 HTMLMediaElement の textTracks 属性が参照する TextTrackList オブジェクトで発火させるはずです。

      7. このトラックの coded frames を格納するための新しい track buffer を作成する。
      8. このトラックの track descriptiontrack buffer に追加する。
    5. active track flag が true に等しい場合、次の手順を実行する:
      1. この SourceBufferactiveSourceBuffers に追加する。
      2. タスクをキューして イベントを発火し、 addsourcebuffer という名前のイベントを activeSourceBuffers で発火する。
    6. [[first initialization segment received flag]] を true に設定する。
  6. [[pending initialization segment for changeType flag]] を false に設定する。
  7. active track flag が true に等しい場合、次の手順を実行する:
  8. parent media sourcemirror if necessary アルゴリズムを用いて、 Window で以下の手順を実行する:
    1. HTMLMediaElementreadyState 属性が HAVE_CURRENT_DATA より大きい場合、 HTMLMediaElementreadyState 属性を HAVE_METADATA に設定する。

      HTMLMediaElement ready states [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性があります。

  9. sourceBuffers 内の各オブジェクトが、 parent media source において [[first initialization segment received flag]] が true に等しい場合、 parent media sourcemirror if necessary アルゴリズムを用いて、 次の手順を Window で実行する:
    1. HTMLMediaElementreadyState 属性が HAVE_NOTHING の場合、 HTMLMediaElementreadyState 属性を HAVE_METADATA に設定する。

      HTMLMediaElement ready states [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性があります。 HAVE_NOTHING から HAVE_METADATA への遷移が発生した場合、メディア要素上で タスクをキューして イベントを発火し、 loadedmetadata という名前のイベントを発火させる HTMLMediaElement のロジックをトリガーすべきです。

5.5.8 コーデッドフレーム処理

完全な coded framessegment parser loop によってパースされたとき、以下の手順を実行する:

  1. media segment 内の各 coded frame について、次の手順を実行する:

    1. Loop Top:
      [[generate timestamps flag]] が true に等しい場合:
      1. presentation timestamp を 0 とする。
      2. decode timestamp を 0 とする。
      それ以外:
      1. presentation timestamp を、coded frame の presentation timestamp(秒)の 倍精度浮動小数点表現とする。

        時刻付きテキストフレームでは、プレゼンテーションおよびデコードのタイムスタンプを決定するために特別な処理が必要になる場合がある。これは、基礎となるフォーマットに明示的に存在しないか、フレームの順序に依存する可能性があるためである。MPEG2-TS の PSI データのようなメタデータテキストトラックの中には、暗黙のタイムスタンプしか持たないものもある。これらの状況に対するフォーマット固有の規則は、byte stream format specifications または別の拡張仕様に記載されるべきである(SHOULD)。

      2. decode timestamp を、coded frame のデコードタイムスタンプ(秒)の 倍精度浮動小数点表現とする。

        実装は内部的にタイムスタンプを倍精度浮動小数点で格納する必要はない。ここでこの表現を用いるのは、HTML 仕様でのタイムスタンプの表現に合わせるためである。意図は、timestampOffset を加えることで、バイトストリームフォーマットが用いる基礎のタイムスタンプ表現でロールオーバーが生じうるという事実に対処するための不要な複雑さをアルゴリズムに加えることなく、挙動を明確にすることにある。実装は任意の内部表現を用いてよいが、timestampOffset の加算は、倍精度浮動小数点表現を用いた場合と同様の挙動になるべきである(SHOULD)。

    2. frame duration を、coded frame の duration(秒)の 倍精度浮動小数点表現とする。
    3. mode が "sequence" に等しく、 [[group start timestamp]] が設定されている場合、次の手順を実行する:
      1. timestampOffset を、[[group start timestamp]] から presentation timestamp を引いた値に設定する。
      2. [[group end timestamp]][[group start timestamp]] に等しく設定する。
      3. すべての track buffersneed random access point flag を true に設定する。
      4. [[group start timestamp]] を未設定にする。
    4. timestampOffset が 0 でない場合、次の手順を実行する:

      1. timestampOffsetpresentation timestamp に加える。
      2. timestampOffsetdecode timestamp に加える。
    5. track buffer を、coded frame が追加される track buffer とする。
    6. track bufferlast decode timestamp が設定されており、 decode timestamplast decode timestamp より小さい場合:
      OR
      track bufferlast decode timestamp が設定されており、 decode timestamplast decode timestamp の差が last frame duration の 2 倍を超える場合:
      1. mode が "segments" に等しい場合:
        [[group end timestamp]]presentation timestamp に設定する。
        mode が "sequence" に等しい場合:
        [[group start timestamp]][[group end timestamp]] に等しく設定する。
      2. すべての track bufferslast decode timestamp を未設定にする。
      3. すべての track bufferslast frame duration を未設定にする。
      4. すべての track buffershighest end timestamp を未設定にする。
      5. すべての track buffersneed random access point flag を true に設定する。
      6. 現在の coded frame の処理を再開するため、 上の Loop Top 手順へジャンプする。
      それ以外:
      続行する。
    7. frame end timestamp を、 presentation timestampframe duration の和とする。
    8. presentation timestampappendWindowStart より小さい場合、 need random access point flag を true に設定し、coded frame を破棄して、 ループの先頭にジャンプして次の coded frame の処理を開始する。

      実装の中には、presentation timestampappendWindowStart より小さい coded frames を収集し、 presentation timestampappendWindowStart 以上となる最初の coded frame でスプライスを生成することを選ぶものもある(たとえそのフレームが random access point でなくても)。これをサポートするには複数のデコーダや実時間より速いデコードが必要となるため、現時点ではこの挙動は規範的要件とはしない。

    9. frame end timestampappendWindowEnd より大きい場合、 need random access point flag を true に設定し、coded frame を破棄して、 ループの先頭にジャンプして次の coded frame の処理を開始する。

      実装の中には、presentation timestampappendWindowEnd より小さく、かつ frame end timestampappendWindowEnd より大きい coded frames を収集し、収集時点で append window に含まれる区間と、 後で処理されるフレームのうち収集済みフレームの末尾と部分的に重なる先頭区間をまたいでスプライスを生成することを選ぶものもある。これをサポートするには複数のデコーダや実時間より速いデコードが必要となるため、現時点ではこの挙動は規範的要件とはしない。 appendWindowStart をまたぐ coded frames の収集と組み合わせることで、実装はギャップレスな音声スプライシングをサポートしうる(MAY)。

    10. track bufferneed random access point flag が true に等しい場合、 次の手順を実行する:
      1. coded frame が random access point でない場合、coded frame を破棄し、ループの先頭にジャンプして次の coded frame の処理を開始する。
      2. track bufferneed random access point flag を false に設定する。
    11. spliced audio frame を、音声スプライス情報を保持する未設定の変数とする。
    12. spliced timed text frame を、タイムドテキストのスプライス情報を保持する未設定の変数とする。
    13. track bufferlast decode timestamp が未設定で、 presentation timestamptrack buffer 内のある coded framepresentation interval に入っている場合、次の手順を実行する:
      1. overlapped frame を、上記条件に一致する track buffer 内の coded frame とする。
      2. track buffer が音声の coded frames を含む場合:
        audio splice frame アルゴリズムを実行し、 スプライスフレームが返された場合はそれを spliced audio frame に代入する。
        track buffer が動画の coded frames を含む場合:
        1. remove window timestamp を、 overlapped framepresentation timestamp に 1 マイクロ秒を加えた値とする。
        2. presentation timestampremove window timestamp より小さい場合、track buffer から overlapped frame を削除する。

          これは、倍精度浮動小数点数と有理数の相互変換で生じうるフレームタイムスタンプ計算の微小誤差を補償するためである。この許容差により、既存フレームの開始時刻から 1 マイクロ秒以内であれば、フレームは既存フレームを置き換えることができる。既存フレームよりわずかに前に来るフレームは、以下の除去手順で対処される。

        track buffer がタイムドテキストの coded frames を含む場合:
        text splice frame アルゴリズムを実行し、 スプライスフレームが返された場合はそれを spliced timed text frame に代入する。
    14. track buffer 内の既存の coded frames を削除する:
      track bufferhighest end timestamp が未設定の場合:
      track buffer から、presentation timestamppresentation timestamp 以上かつ frame end timestamp 未満である すべての coded frames を削除する。
      track bufferhighest end timestamp が設定済みで、かつ presentation timestamp 以上に等しい場合:
      track buffer から、presentation timestamphighest end timestamp 以上かつ frame end timestamp 未満である すべての coded frames を削除する。
    15. 前二つの手順で削除した coded frames に対する 可能なデコード依存性をすべて取り除くため、前二つの手順で削除したフレームと、その後に現れる次の random access point との間にある track buffer 内のすべての coded frames を削除する。

      次の random access point まで すべての coded frames を削除することは、 保守的なデコード依存性の見積もりである。これは、削除されたフレームと次の random access point の間の全フレームが、 削除されたフレームに依存していると仮定しているためである。

    16. spliced audio frame が設定されている場合:
      spliced audio frametrack buffer に追加する。
      spliced timed text frame が設定されている場合:
      spliced timed text frametrack buffer に追加する。
      それ以外:
      coded frame を、 presentation timestampdecode timestampframe duration とともに track buffer に追加する。
    17. track bufferlast decode timestampdecode timestamp に設定する。
    18. track bufferlast frame durationframe duration に設定する。
    19. track bufferhighest end timestamp が未設定であるか、 frame end timestamphighest end timestamp より大きい場合、 track bufferhighest end timestampframe end timestamp に設定する。

      双方向予測により、decode timestamps は単調増加でも、 presentation timestamp は単調増加とならない場合があるため、 「より大きい」かどうかのチェックが必要となる。

    20. frame end timestamp[[group end timestamp]] より大きい場合、 [[group end timestamp]]frame end timestamp に等しく設定する。
    21. [[generate timestamps flag]] が true に等しい場合、 timestampOffsetframe end timestamp に等しく設定する。
  2. HTMLMediaElementreadyState 属性が HAVE_METADATA であり、新しい coded frames によって HTMLMediaElementbuffered が 現在の再生位置に対応する TimeRanges を持つようになった場合、 HTMLMediaElementreadyState 属性を HAVE_CURRENT_DATA に設定する。

    HTMLMediaElement ready states [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性がある。

  3. HTMLMediaElementreadyState 属性が HAVE_CURRENT_DATA であり、新しい coded frames によって HTMLMediaElementbuffered が、 現在の再生位置を含み、かつ現在の再生位置より先の時間も含む TimeRanges を持つようになった場合、 HTMLMediaElementreadyState 属性を HAVE_FUTURE_DATA に設定する。

    HTMLMediaElement ready states [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性がある。

  4. HTMLMediaElementreadyState 属性が HAVE_FUTURE_DATA であり、新しい coded frames によって HTMLMediaElementbuffered が、 現在の再生位置と、途切れない再生を確保するのに十分なデータ を含む TimeRanges を持つようになった場合、 HTMLMediaElementreadyState 属性を HAVE_ENOUGH_DATA に設定する。

    HTMLMediaElement ready states [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は、 HTMLMediaElement 上でイベントをトリガーする可能性がある。

  5. media segment に、現在の duration を超えるデータが含まれている場合、 duration change アルゴリズムを、 new duration を現在の duration と [[group end timestamp]] の最大値に設定して実行する。

5.5.9 コーデッドフレーム除去

特定の時間範囲の coded frames を SourceBuffer から除去する必要がある場合、以下の手順を実行する:

  1. start を、除去範囲の開始 presentation timestamp とする。
  2. end を、除去範囲の終了 presentation timestamp とする。
  3. この SourceBuffer 内の各 track buffer について、以下の手順を実行する:

    1. remove end timestampduration の現在値とする。
    2. この track bufferrandom access point タイムスタンプがあり、 それが end 以上なら、 remove end timestamp をその random access point タイムスタンプに更新する。

      random access point のタイムスタンプはトラックごとに異なる場合がある。これは通常、トラック内の coded frames の依存関係が他トラックの依存関係とは異なるためである。

    3. この track buffer から、 開始タイムスタンプが start 以上かつ remove end timestamp 未満のメディアデータをすべて除去する。
      1. 除去された各フレームについて、フレームの decode timestamp がそのトラックの last decode timestamp と等しい場合、次の手順を実行する:

        mode が "segments" に等しい場合:
        [[group end timestamp]]presentation timestamp に設定する。
        mode が "sequence" に等しい場合:
        [[group start timestamp]][[group end timestamp]] に等しく設定する。
      2. すべての track bufferslast decode timestamp を未設定にする。
      3. すべての track bufferslast frame duration を未設定にする。
      4. すべての track buffershighest end timestamp を未設定にする。
      5. すべての track buffersneed random access point flag を true に設定する。
    4. 前の手順で除去された coded frames に対する可能なデコード依存性をすべて取り除くため、前の手順で除去されたフレームと、その後に現れる次の random access point との間にある この track buffer 内のすべての coded frames を削除する。

      次の random access point まで すべての coded frames を削除することは、 保守的なデコード依存性の見積もりである。これは、除去されたフレームと次の random access point の間の全フレームが、 除去されたフレームに依存していると仮定しているためである。

    5. このオブジェクトが activeSourceBuffers にあり、 現在の再生位置start 以上かつ remove end timestamp 未満であり、 HTMLMediaElementreadyStateHAVE_METADATA より大きい場合、 HTMLMediaElementreadyState 属性を HAVE_METADATA に設定し、 再生を停止する。

      HTMLMediaElement ready states [HTML] のロジックに従い、 HTMLMediaElementreadyState の変更は HTMLMediaElement 上でイベントをトリガーする可能性がある。

      この遷移は、現在位置のメディアデータが除去されたため発生する。現在の再生位置 のメディアが再追加されるか、 3.15.5 選択/有効トラック状態の変更 が行われるまで、再生は進行できない。

  4. [[buffer full flag]] が true で、 このオブジェクトが新たなバイトを受け入れ可能な場合、 [[buffer full flag]] を false に設定する。

5.5.10 コーデッドフレーム追い出し

このアルゴリズムは新しいデータが SourceBuffer に追加される際、空き領域を確保するために実行される。

  1. new data を、これから追加されるデータとする。
    Issue 289: 編集?コーデッドフレーム追い出しアルゴリズムは「buffer full flag」が |new data| に応じて即座に更新されうる旨を記述する必要あり

    ここで、実装は MAY [[buffer full flag]] を ここで true に設定することを選んでもよい。これは、[[input buffer]] に既存のバイト列と new data を加えた場合、 SourceBuffer の容量を超えると予測されるときなどに、より積極的なプッシュバックを可能にするためである。実際、少なくとも1つの実装がこれを既に行っている。

  2. [[buffer full flag]] が false の場合、この手順を中止する。
  3. removal ranges を、 new data を格納するためにプレゼンテーションから追い出せる プレゼンテーション時間範囲リストとする。

    実装は MAY removal ranges の選択方法を変えることができるため、 ウェブアプリケーションは特定の挙動に依存 SHOULD NOT すべきでない。 ウェブアプリケーションは buffered 属性を使い、 バッファ済みデータの一部が追い出されたかどうか観察できる。

  4. removal ranges の各範囲について、 coded frame removal アルゴリズムを startend を それぞれ範囲の開始・終了タイムスタンプとして実行する。

5.5.11 音声スプライスフレーム

coded frame processing アルゴリズムが 重複する2つの音声 coded frames のスプライスフレーム生成を必要とした時、以下の手順を実行する:

  1. track buffer を、スプライスを格納する track buffer とする。
  2. new coded frame を、track buffer に追加される新しい coded frame(スプライスが必要となった原因)とする。
  3. presentation timestampnew coded framepresentation timestamp とする。
  4. decode timestampnew coded frame の decode timestamp とする。
  5. frame durationnew coded framecoded frame duration とする。
  6. overlapped frametrack buffer 内で presentation intervalpresentation timestamp を含む coded frame とする。
  7. presentation timestampdecode timestampoverlapped frame のサンプルレートに基づき、最も近いオーディオサンプルタイムスタンプに更新する。両方のサンプルタイムスタンプから等距離の場合は高い方のタイムスタンプを使う(例:floor(x * sample_rate + 0.5) / sample_rate)。

    例:

    • overlapped framepresentation timestamp が 10。
    • overlapped frame のサンプルレートが 8000 Hz
    • presentation timestamp が 10.01255
    • decode timestamp が 10.01255

    presentation timestamp および decode timestamp は 10.0125 に更新される(10.01255 は 10 + 100/8000 (10.0125) により近い)。

  8. ユーザーエージェントがクロスフェードをサポートしない場合、次の手順を実行する:
    1. overlapped frametrack buffer から削除する。
    2. 以下のプロパティを持つ無音フレームを track buffer に追加する:

      実装によっては、無音フレーム前後の coded frames にフェードをかけて、遷移を滑らかにするものもある(MAY)。

    3. スプライスフレームを返さずに呼び出し元に戻る。

      これは track buffer から overlapped frame が最初から存在しなかったかのように new coded frame を追加できるようにするため。

  9. frame end timestamppresentation timestampframe duration の和とする。
  10. splice end timestamppresentation timestamp と スプライス持続時間(5ミリ秒)の和とする。
  11. fade out coded framesoverlapped frame と、 presentation timestamp より大きく splice end timestamp 未満の presentation timestamp を持つ track buffer 内の追加フレームとする。
  12. fade out coded frames に含まれるすべてのフレームを track buffer から削除する。
  13. 以下のプロパティを持つスプライスフレームを返す:
    • overlapped framepresentation timestamppresentation timestamp とする。
    • overlapped framedecode timestampdecode timestamp とする。
    • overlapped framecoded frame duration を、frame end timestamppresentation timestamp の差に設定する。
    • fade out coded frames は fade out coded frames とする。
    • fade in coded frame は new coded frame とする。

      new coded frame の持続時間が 5 ミリ秒未満の場合、スプライスの正しい描画には new coded frame の後に追加される coded frames も必要となる。

    • splice timestamp は presentation timestamp とする。

    このスプライスフレームの描画詳細は audio splice rendering アルゴリズムを参照。

5.5.12 音声スプライスレンダリング

メディア要素が audio splice frame アルゴリズムで生成されたスプライスフレームをレンダリングする必要がある場合、以下の手順を実行する:

  1. fade out coded frames を、スプライス時にフェードアウトされる coded frames とする。
  2. fade in coded frames を、スプライス時にフェードインされる coded frames とする。
  3. presentation timestampfade out coded frames の最初の coded frame の presentation timestamp とする。
  4. end timestamppresentation timestampcoded frame durationfade in coded frames の最後のフレーム)との和とする。
  5. splice timestamp を、スプライス開始点の presentation timestampfade in coded frames の最初のフレームの timestamp)とする。
  6. splice end timestampsplice timestamp + 5ミリ秒とする。
  7. fade out samplesfade out coded frames をデコードして生成したサンプルとする。
  8. fade out samplespresentation timestampsplice end timestamp のみ含むようにトリムする。
  9. fade in samplesfade in coded frames をデコードして生成したサンプルとする。
  10. fade out samplesfade in samples のサンプルレートやチャンネルレイアウトが一致しない場合、両者を共通のサンプルレート・チャンネルレイアウトに変換する。
  11. output samples を出力サンプルを格納するバッファとする。
  12. splice timestampsplice end timestampfade out samples に対し、開始ゲイン1・終了ゲイン0の線形フェードアウトを適用する。
  13. splice timestampsplice end timestampfade in samples に対し、開始ゲイン0・終了ゲイン1の線形フェードインを適用する。
  14. presentation timestampsplice timestampfade out samplesoutput samples にコピーする。
  15. splice timestampsplice end timestamp の各サンプルについて、 fade out samples のサンプルと対応する fade in samples のサンプルの和を計算し、output samples に格納する。
  16. splice end timestampend timestampfade in samplesoutput samples にコピーする。
  17. output samples をレンダリングする。

このアルゴリズムの図解です。

Audio splice diagram

5.5.13 テキストスプライスフレーム

coded frame processing アルゴリズムが 重複する2つのタイムドテキスト coded frames のスプライスフレーム生成を必要とした時、以下の手順を実行する:

  1. track buffer を、スプライスを格納する track buffer とする。
  2. new coded frame を、track buffer に追加される新しい coded frame(スプライスが必要となった原因)とする。
  3. presentation timestampnew coded framepresentation timestamp とする。
  4. decode timestampnew coded frame の decode timestamp とする。
  5. frame durationnew coded framecoded frame duration とする。
  6. frame end timestamppresentation timestampframe duration の和とする。
  7. first overlapped frametrack buffer 内で presentation intervalpresentation timestamp を含む coded frame とする。
  8. overlapped presentation timestampfirst overlapped framepresentation timestamp とする。
  9. overlapped framesfirst overlapped frame および、presentation timestamp より大きく frame end timestamp 未満の presentation timestamp を持つ track buffer 内の追加フレームとする。
  10. overlapped frames に含まれるすべてのフレームを track buffer から削除する。
  11. first overlapped framecoded frame durationpresentation timestampoverlapped presentation timestamp に更新する。
  12. first overlapped frametrack buffer に追加する。
  13. スプライスフレームを返さずに呼び出し元に戻る。

    これは track buffer 内のフレームと new coded frame が最初から重複していなかったかのように new coded frame を追加できるようにするため。

6. SourceBufferList インターフェース

SourceBufferListSourceBuffer オブジェクトの単純なコンテナオブジェクトです。 配列として読み取り専用アクセスを提供し、リストが変更された際にイベントを発火します。

WebIDL[Exposed=(Window,DedicatedWorker)]
interface SourceBufferList : EventTarget {
  readonly attribute unsigned long length;

  attribute EventHandler onaddsourcebuffer;
  attribute EventHandler onremovesourcebuffer;

  getter SourceBuffer (unsigned long index);
};

6.1 属性

lengthunsigned long (読み取り専用)

リスト内の SourceBuffer オブジェクト数を示します。

onaddsourcebufferEventHandler

addsourcebuffer イベント用のイベントハンドラです。

onremovesourcebufferEventHandler

removesourcebuffer イベント用のイベントハンドラです。

6.2 メソッド

getter

リスト内の SourceBuffer オブジェクトを配列演算子([])でアクセスできます。

このメソッドが呼び出された時、ユーザーエージェントは次の手順を実行します:

  1. indexlength 属性以上であれば、undefined を返し手順を中止します。
  2. index 番目の SourceBuffer オブジェクトをリストから返します。

6.3 イベント概要

イベント名 インターフェース 発火タイミング
addsourcebuffer Event SourceBuffer が リストに追加された時。
removesourcebuffer Event SourceBuffer が リストから削除された時。

7. ManagedMediaSource インターフェース

ManagedMediaSourceMediaSource を拡張し、メモリ内容を積極的に管理するものです。 MediaSource と異なり、ユーザーエージェントmemory cleanup アルゴリズムを使って、 sourceBuffersManagedSourceBuffer で構成)から 任意の理由でコンテンツを追い出すことができます。

: 追い出し理由
WebIDL[Exposed=(Window,DedicatedWorker)]
interface ManagedMediaSource : MediaSource {
  constructor();
  readonly attribute boolean streaming;
  attribute EventHandler onstartstreaming;
  attribute EventHandler onendstreaming;
};

7.1 属性

streaming

取得時:

  1. 属性の現在値を返す。

7.2 イベント概要

イベント名 インターフェース 発火タイミング
startstreaming Event ManagedMediaSourcestreaming 属性が false から true に変化した時。
endstreaming Event ManagedMediaSourcestreaming 属性が true から false に変化した時。

7.3 アルゴリズム

7.3.1 ManagedSourceBuffer 監視

以下の手順は、SourceBuffer Monitoring アルゴリズムが定期的に実行される際に実行されます。

途切れない再生のために十分な管理データがある とは、 ユーザーエージェントが意味ある時間停止することなくプレゼンテーションを再生できる十分なデータが現在あると判断する実装依存の条件です。 この条件は常に評価され、streaming の値の遷移タイミングを決定します。 これらの遷移は、ユーザーエージェントが十分なデータがバッファ済みか、より多くのデータが必要かを示します。

効率的にデータ取得・バッファできる とは、 ユーザーエージェントが省エネ的に新規データを取得し、望ましいメモリ使用を達成できると判断する実装依存の条件です。

  1. MediaSourceSourceBuffer Monitoring アルゴリズムを実行する。
  2. can play uninterrupted and efficiently フラグを次の条件で true とする: buffered 属性が 現在の再生位置を含む TimeRanges を持ち、 途切れない再生のために十分な管理データがある かつ 効率的にデータ取得・バッファできる
    can play uninterrupted and efficientlystreaming と等しくない場合、 要素タスクをキューし、 メディア要素上で 以下の手順を実行する:
    1. thisstreaming 属性を can play uninterrupted and efficiently に設定する。
    2. can play uninterrupted and efficiently が false なら イベントを発火し、 startstreaming イベントを ManagedMediaSource で発火する。
    3. それ以外の場合は イベントを発火し、 endstreaming イベントを ManagedMediaSource で発火する。

7.3.2 メモリクリーンアップ

  1. thissourceBuffers 内の 各 buffer について:
    1. buffermemory cleanup アルゴリズムを実行する。

8. BufferedChangeEvent インターフェース

WebIDL[Exposed=(Window,DedicatedWorker)]
interface BufferedChangeEvent : Event {
  constructor(DOMString type, optional BufferedChangeEventInit eventInitDict = {});

  [SameObject] readonly attribute TimeRanges addedRanges;
  [SameObject] readonly attribute TimeRanges removedRanges;
};

dictionary BufferedChangeEventInit : EventInit {
  TimeRanges addedRanges;
  TimeRanges removedRanges;
};

8.1 属性

addedRanges
直近の updatestartupdateend の各イベントの間に追加された時間範囲(これは直近に実行された coded frame processing アルゴリズムの実行中に発生しているはずです)。
removedRanges
直近の updatestartupdateend の各イベントの間に削除された時間範囲(これは直近に実行された coded frame removal または coded frame eviction アルゴリズムの実行中、あるいは ユーザーエージェントが memory cleanup に応じてコンテンツを追い出した結果として発生しているはずです)。

9. ManagedSourceBuffer インターフェース

WebIDL[Exposed=(Window,DedicatedWorker)]
interface ManagedSourceBuffer : SourceBuffer {
  attribute EventHandler onbufferedchange;
};

9.1 属性

onbufferedchange

イベントハンドラー IDL 属性であり、 その イベントハンドラーのイベントタイプbufferedchange です。

9.2 イベント概要

イベント名 インターフェース 発火タイミング
bufferedchange BufferedChangeEvent ManagedSourceBuffer の buffered 範囲が、 appendBuffer()remove()endOfStream() の呼び出し後、 またはユーザーエージェントが memory cleanup アルゴリズムを実行した結果として変更されたときに発火します。

9.3 アルゴリズム

9.3.1 Buffered Change

ManagedSourceBuffer buffer に対して実行された、bufferbuffered を変更する原因となるすべての操作が完了した時、以下の手順を実行します。 つまり、appendBuffer()remove()、または memory cleanup アルゴリズムが完了したタイミングです。

  1. previous buffered ranges を、変更が発生する前の buffered 属性の値とする。
  2. new buffered ranges を、新しい buffered TimeRanges とする。
  3. added を、 new buffered ranges から previous buffered ranges を差し引いた結果とする。
  4. removed を、 previous buffered ranges から new buffered ranges を差し引いた結果とする。
  5. eventInitDict を新しい BufferedChangeEventInit 辞書として作成し、 その addedRangesadded を、 removedRangesremoved をそれぞれ設定する。
  6. タスクをキューして、 イベントを発火し、 BufferedChangeEvent インターフェースを用いて buffer に対して bufferedchange という名前のイベントを、 eventInitDict で初期化して発火する。

9.3.2 メモリクリーンアップ

  1. this が 親の ManagedMediaSourceactiveSourceBuffers に 含まれていない場合:
    1. coded frame removal アルゴリズムを、start を 0、end を正の無限大に設定して実行し、これらの手順を中止する。
  2. removal ranges を、プレゼンテーションから追い出すことで currentTime から再取得可能となるまでの間、途切れない再生を確保できるプレゼンテーション時間範囲のリストとする。

    実装は removal ranges の選択に異なる戦略を用いることができるため、 ウェブアプリケーションは特定の挙動に依存すべきではありません。ウェブアプリケーションは bufferedchange イベントを監視して、 バッファ済みデータの一部が追い出されたかどうかを観測します。

  3. removal ranges の各範囲について、 coded frame removal アルゴリズムを、 start および end を それぞれ範囲の開始・終了タイムスタンプに設定して実行する。

10. HTMLMediaElement 拡張

本節では、要素に MediaSource がアタッチされている場合に、既存の HTMLMediaElementseekable および buffered 属性が MUST 返すべき内容と、 既存の HTMLMediaElementsrcObject 属性が MediaSourceHandle オブジェクトに設定された際に 行わなければならないこと(MUST)を規定します。

HTMLMediaElementseekable 属性は、以下の手順に基づいて作成された新しい静的な 正規化済み TimeRanges オブジェクト を返します。

  1. MediaSource が 終了済みまたはクローズ中の DedicatedWorkerGlobalScope 内で構築されている場合、空の TimeRanges オブジェクトを返して、これらの手順を中止する。

    このケースは、terminate() によって終了、またはユーザーエージェントが terminate a worker を実行した結果として 当該 MediaSource の DedicatedWorkerGlobalScope が破棄された場合など、DedicatedWorkerGlobalScope で構築された MediaSource において、バッファ済みまたはシーク可能なメディアに関する過去の情報を保持しない実装を扱うことを意図しています。 これは例えば、最終的に close() 実行の結果として起こり得ます。

    Issue 277: MSE-in-Workers: MediaSource のワーカー終了時に、アタッチされた要素をエラーへ(最終的に)遷移させるべきか/メディア要素は何をすべきか? mse-in-workers

    ワーカー MediaSource に紐づくコンテキストが破棄された場合、(最終的に)メディア要素のエラー遷移があるべきでしょうか? ワーカー MSE の実験的な Chromium 実装では、そのコンテキスト破壊の前後で要素の readyState、networkState、error は同一のままですが、 seekable と buffered の各属性は空の TimeRange を返します。

  2. recent duration および recent live seekable range を、それぞれ duration[[live seekable range]] の直近の値として、 次のように決定する:
    MediaSourceWindow で構築されている場合
    recent durationduration とし、 recent live seekable range[[live seekable range]] とする。
    それ以外の場合:
    recent durationrecent live seekable range を、それぞれ直近の duration[[live seekable range]] の値とし、 それらは MediaSource[[port to main]] に 送信する暗黙メッセージを各変更時に処理することで更新される。
  3. recent duration が NaN に等しい場合:
    空の TimeRanges オブジェクトを返す。
    recent duration が正の無限大に等しい場合:
    1. recent live seekable range が空でない場合:
      1. union ranges を、 recent live seekable rangeHTMLMediaElementbuffered 属性の合併とする。
      2. union ranges 内の最も早い開始時刻を開始時刻、 union ranges 内の最大の終了時刻を終了時刻とする単一の範囲を返し、これらの手順を中止する。
    2. HTMLMediaElementbuffered 属性が空の TimeRanges オブジェクトを返すなら、空の TimeRanges オブジェクトを返してこれらの手順を中止する。
    3. 開始時刻 0、終了時刻を HTMLMediaElementbuffered 属性が報告する最大の終了時刻とする単一の範囲を返す。
    それ以外の場合:
    開始時刻 0、終了時刻を recent duration とする単一の範囲を返す。

HTMLMediaElementbuffered 属性は、以下の手順に基づく静的な 正規化済み TimeRanges オブジェクト を返します。

  1. MediaSource が 終了済みまたはクローズ中の DedicatedWorkerGlobalScope 内で構築されている場合、空の TimeRanges オブジェクトを返して、これらの手順を中止する。

    このケースは、terminate() によって終了、またはユーザーエージェントが terminate a worker を実行した結果として 当該 MediaSource の DedicatedWorkerGlobalScope が破棄された場合など、DedicatedWorkerGlobalScope で構築された MediaSource において、バッファ済みまたはシーク可能なメディアに関する過去の情報を保持しない実装を扱うことを意図しています。 これは例えば、最終的に close() 実行の結果として起こり得ます。

    Issue 277: MSE-in-Workers: MediaSource のワーカー終了時に、アタッチされた要素をエラーへ(最終的に)遷移させるべきか/メディア要素は何をすべきか? mse-in-workers

    ワーカー MediaSource に紐づくコンテキストが破棄された場合、(最終的に)メディア要素のエラー遷移があるべきでしょうか? ワーカー MSE の実験的な Chromium 実装では、そのコンテキスト破壊の前後で要素の readyState、networkState、error は同一のままですが、 seekable と buffered の各属性は空の TimeRange を返します。

  2. recent intersection ranges を次のように決定する:
    MediaSourceWindow で構築されている場合
    1. recent intersection ranges を 空の TimeRanges オブジェクトとする。
    2. activeSourceBuffers.length が 0 に等しくない場合、次を実行する:
      1. active ranges を、 activeSourceBuffers 内の 各 SourceBuffer オブジェクトの buffered が返す範囲とする。
      2. highest end time を、 active ranges 内の 最大の終了時刻とする。
      3. recent intersection ranges を、 0 から highest end time までの 単一範囲を含む TimeRanges オブジェクトとする。
      4. SourceBuffer の各オブジェクトについて、 activeSourceBuffers 内を 反復し、次を実行する:
        1. source ranges を、 現在の buffered 属性が返す範囲とする。
        2. readyState が "ended" の場合、 source ranges の最後の範囲の終了時刻を highest end time に設定する。
        3. new intersection ranges を、 recent intersection rangessource ranges の交差として求める。
        4. recent intersection ranges の 範囲を new intersection ranges に置き換える。
    それ以外の場合:
    recent intersection ranges を、 Window のケースでの手順の結果として得られる TimeRanges とするが、 MediaSource とその SourceBuffer オブジェクトを それぞれの DedicatedWorkerGlobalScope 内で実行し、 [[port to main]] を用いた暗黙メッセージにより、 activeSourceBuffersreadyState、 および各 buffered 属性の値を変えうる あらゆるバッファリング状態の更新ごとに通信する。

    recent intersection ranges の再計算と通信を頻繁に行うオーバーヘッドは、 クロスコンテキスト通信モデル で言及されている共有メモリとロックなど、 他のメカニズムを用いてオンデマンドでこの情報を問い合わせられる実装の柔軟性を許容する理由の一つです。

  3. この属性の現在値が本アルゴリズムによって設定されていない、または recent intersection ranges が現在値と全く同じ範囲情報を含まない場合、 この属性の現在値を recent intersection ranges に更新する。
  4. この属性の現在値を返す。

HTMLMediaElementsrcObject 属性に MediaSourceHandle が代入された場合、 要素の load アルゴリズムを呼び出す前に行われる拡張された HTMLMediaElementsrcObject セッターの同期ステップの一部として、 当該 MediaSourceHandle[[has ever been assigned as srcobject]] を true に設定する。

これにより、その MediaSourceHandle オブジェクトを再度転送することが 将来にわたって防止され、試行された場合に明確な同期例外を可能にします。

Issue

MediaSourceHandle は、 HTMLMediaElement の MediaProvider IDL typedef およびメディアプロバイダーオブジェクトに関する関連テキストに追加される必要があります。

11. AudioTrack 拡張

本節では、[HTML] の AudioTrack 定義に対する拡張を規定する。

WebIDL[Exposed=(Window,DedicatedWorker)]
partial interface AudioTrack {
  readonly attribute SourceBuffer? sourceBuffer;
};
Issue 280: MSE-in-Workers: {Audio,Video,Text}Track{,List} IDL in HTML において Exposed に DedicatedWorker を追加で必要とする mse-in-workers
[HTML] の AudioTrack は Window + DedicatedWorker への公開が必要である。

属性

sourceBufferSourceBuffer、 読み取り専用 , nullable

取得時、次の手順を実行する:

当該トラックが、このトラックと同じ realm で作成された SourceBuffer によって生成され、かつその SourceBuffer が、その 親メディアソースsourceBuffers 属性から削除されていない場合:
当該トラックを作成した SourceBuffer を返す。
それ以外の場合:
null を返す。
例えば、DedicatedWorkerGlobalScopeSourceBuffer が、 Window にある内部の create track mirror ハンドラにこのトラックの作成を通知した場合、 その Window 側のコピーは この属性に対して null を返す。

12. VideoTrack 拡張

本節では、[HTML] の VideoTrack 定義に対する拡張を規定する。

WebIDL[Exposed=(Window,DedicatedWorker)]
partial interface VideoTrack {
  readonly attribute SourceBuffer? sourceBuffer;
};
Issue 280: MSE-in-Workers: {Audio,Video,Text}Track{,List} IDL in HTML において Exposed に DedicatedWorker を追加で必要とする mse-in-workers
[HTML] の VideoTrack は Window + DedicatedWorker への公開が必要である。

属性

sourceBufferSourceBuffer、 読み取り専用 , nullable

取得時、次の手順を実行する:

当該トラックが、このトラックと同じ realm で作成された SourceBuffer によって生成され、かつその SourceBuffer が、その 親メディアソースsourceBuffers 属性から削除されていない場合:
当該トラックを作成した SourceBuffer を返す。
それ以外の場合:
null を返す。
例えば、DedicatedWorkerGlobalScopeSourceBuffer が、 Window にある内部の create track mirror ハンドラにこのトラックの作成を通知した場合、 その Window 側のコピーは この属性に対して null を返す。

13. TextTrack 拡張

本節では、[HTML] の TextTrack 定義に対する拡張を規定する。

WebIDL[Exposed=(Window,DedicatedWorker)]
partial interface TextTrack {
  readonly attribute SourceBuffer? sourceBuffer;
};
Issue 280: MSE-in-Workers: {Audio,Video,Text}Track{,List} IDL in HTML において Exposed に DedicatedWorker を追加で必要とする mse-in-workers
[HTML] の TextTrack は Window + DedicatedWorker への公開が必要である。

属性

sourceBufferSourceBuffer、 読み取り専用 , nullable

取得時、次の手順を実行する:

当該トラックが、このトラックと同じ realm で作成された SourceBuffer によって生成され、かつその SourceBuffer が、その 親メディアソースsourceBuffers 属性から削除されていない場合:
当該トラックを作成した SourceBuffer を返す。
それ以外の場合:
null を返す。
例えば、DedicatedWorkerGlobalScopeSourceBuffer が、 Window にある内部の create track mirror ハンドラにこのトラックの作成を通知した場合、 その Window 側のコピーは この属性に対して null を返す。

14. Byte Stream Formats

SourceBuffer に対して appendBuffer() を通じて提供されるバイト列は、 論理的なバイトストリームを形成する。これらのバイトストリームの形式と意味は、byte stream format specifications で定義される。バイトストリーム形式 レジストリ [MSE-REGISTRY] は、 addSourceBuffer()isTypeSupported()、 または changeType() に渡されうる MIME タイプと、 その MIME タイプを用いて新たに追加されたデータを解析する SourceBuffer が期待するバイトストリーム形式との 対応付けを提供する。相互運用性を促進するため、実装はサポートするバイトストリーム形式に対するマッピングを登録することが推奨される。 バイトストリーム形式レジストリ [MSE-REGISTRY] は、 これらのマッピングの正規の情報源である。実装がレジストリに掲載された MIME タイプのサポートを表明する場合、 その SourceBuffer 実装は、 レジストリエントリに記載された byte stream format specificationMUST 準拠しなければならない。

Note

レジストリにおけるバイトストリーム形式仕様は、新しいストレージ形式を定義することを意図していない。これは単に、 本仕様の実装が受理する既存ストレージ形式構造のサブセットを概説するものである。

Note

バイトストリームの解析と検証は、segment parser loop アルゴリズムで実装される。

本節は、すべてのバイトストリーム形式仕様に対する一般要件を示す:

バイトストリーム仕様は、少なくとも上記要件が満たされることを保証する制約を定義しなければならない(MUST)。 実装を簡素化するためなど、追加の制約を定義してもよい(MAY)。

15. 適合性

非規範的とマークされた節に加え、本仕様のすべてのオーサリングガイドライン、図、例、注記は非規範的である。 それ以外の本仕様の内容はすべて規範的である。

本文書における MAYMUSTMUST NOTSHOULDSHOULD NOT というキーワードは、 BCP 14 [RFC2119] [RFC8174] に従って解釈される。これは、それらがここに示すようにすべて大文字で現れる場合に限る。

16.

16.1 Media Source Extensions の使用

<video id="v" autoplay></video>
<script>
const video = document.getElementById("v");
const mediaSource = new MediaSource();
mediaSource.addEventListener("sourceopen", onSourceOpen);
video.src = window.URL.createObjectURL(mediaSource);

async function onSourceOpen(e) {
  const mediaSource = e.target;

  if (mediaSource.sourceBuffers.length > 0) return;

  const sourceBuffer = mediaSource.addSourceBuffer(
    'video/webm; codecs="vorbis,vp8"',
  );

  video.addEventListener("seeking", (e) => onSeeking(mediaSource, e.target));
  video.addEventListener("progress", () =>
    appendNextMediaSegment(mediaSource),
  );

  try {
    const initSegment = await getInitializationSegment();

    if (initSegment == null) {
      // Error fetching the initialization segment. Signal end of stream with an error.
      mediaSource.endOfStream("network");
      return;
    }

    // Append the initialization segment.
    sourceBuffer.addEventListener("updateend", function firstAppendHandler() {
      sourceBuffer.removeEventListener("updateend", firstAppendHandler);

      // Append some initial media data.
      appendNextMediaSegment(mediaSource);
    });

    sourceBuffer.appendBuffer(initSegment);
  } catch (error) {
    // Handle errors that might occur during initialization segment fetching.
    console.error("Error fetching initialization segment:", error);
    mediaSource.endOfStream("network");
  }
}

async function appendNextMediaSegment(mediaSource) {
  if (
    mediaSource.readyState === "closed" ||
    mediaSource.sourceBuffers[0].updating
  )
    return;

  // If we have run out of stream data, then signal end of stream.
  if (!haveMoreMediaSegments()) {
    mediaSource.endOfStream();
    return;
  }

  try {
    const mediaSegment = await getNextMediaSegment();

    // NOTE: If mediaSource.readyState == "ended", this appendBuffer() call will
    // cause mediaSource.readyState to transition to "open". The web application
    // should be prepared to handle multiple "sourceopen" events.
    mediaSource.sourceBuffers[0].appendBuffer(mediaSegment);
  }
  catch (error) {
    // Handle errors that might occur during media segment fetching.
    console.error("Error fetching media segment:", error);
    mediaSource.endOfStream("network");
  }
}

function onSeeking(mediaSource, video) {
  if (mediaSource.readyState === "open") {
    // Abort current segment append.
    mediaSource.sourceBuffers[0].abort();
  }

  // Notify the media segment loading code to start fetching data at the
  // new playback position.
  seekToMediaSegmentAt(video.currentTime);

  // Append a media segment from the new playback position.
  appendNextMediaSegment(mediaSource);
}

function onProgress(mediaSource, e) {
  appendNextMediaSegment(mediaSource);
}

// Example of async function for getting initialization segment
async function getInitializationSegment() {
  // Implement fetching of the initialization segment
  // This is just a placeholder function
}

// Example function for checking if there are more media segments
function haveMoreMediaSegments() {
  // Implement logic to determine if there are more media segments
  // This is just a placeholder function
}

// Example function for getting the next media segment
async function getNextMediaSegment() {
  // Implement fetching of the next media segment
  // This is just a placeholder function
}

// Example function for seeking to a specific media segment
function seekToMediaSegmentAt(currentTime) {
  // Implement seeking logic
  // This is just a placeholder function
}
</script>

16.2 Managed Media Source の使用

<script>
async function setUpVideoStream() {
  // Specific video format and codec
  const mediaType = 'video/mp4; codecs="mp4a.40.2,avc1.4d4015"';

  // Check if the type of video format / codec is supported.
  if (!window.ManagedMediaSource?.isTypeSupported(mediaType)) {
    return; // Not supported, do something else.
  }

  // Set up video and its managed source.
  const video = document.createElement("video");
  const source = new ManagedMediaSource();

  video.controls = true;

  await new Promise((resolve) => {
    video.src = URL.createObjectURL(source);
    source.addEventListener("sourceopen", resolve, { once: true });
    document.body.appendChild(video);
  });

  const sourceBuffer = source.addSourceBuffer(mediaType);

  // Set up the event handlers
  sourceBuffer.onbufferedchange = (e) => {
    console.log("onbufferedchange event fired.");
    console.log(`Added Ranges: ${timeRangesToString(e.addedRanges)}`);
    console.log(`Removed Ranges: ${timeRangesToString(e.removedRanges)}`);
  };

  source.onstartstreaming = async () => {
    const response = await fetch("./videos/bipbop.mp4");
    const buffer = await response.arrayBuffer();
    await new Promise((resolve) => {
      sourceBuffer.addEventListener("updateend", resolve, { once: true });
      sourceBuffer.appendBuffer(buffer);
    });
  };

  source.onendstreaming = async () => {
    // Stop fetching new segments here
  };
}

// Helper function...
function timeRangesToString(timeRanges) {
  const ranges = [];
  for (let i = 0; i < timeRanges.length; i++) {
    ranges.push([timeRanges.start(i), timeRanges.end(i)]);
  }
  return "[" + ranges.map(([start, end]) => `[${start}, ${end})` ) + "]";     
}
</script>
<body onload="setUpVideoStream()"></body>

17. 謝辞

編集者は、Alex Giladi、Bob Lund、Chris Needham、Chris Poole、Chris Wilson、Cyril Concolato、Dale Curtis、David Dorwin、David Singer、Duncan Rowden、François Daoust、Frank Galligan、Glenn Adams、Jer Noble、Joe Steele、John Simmons、Kagami Sascha Rosylight、Kevin Streeter、Marcos Cáceres、Mark Vickers、Matt Ward、Matthew Gregan、 Michael(tm) Smith、Michael Thornburgh、Mounir Lamouri、Paul Adenot、Philip Jägenstedt、 Philippe Le Hegaret、Pierre Lemieux、Ralph Giles、Steven Robertson、Tatsuya Igarashi の本仕様への貢献に感謝する。

A. VideoPlaybackQuality

この節は非規範的である。

本仕様の以前の版で記述されていた動画再生品質メトリクス (例:Candidate Recommendation の第 5 章および第 10 章)は、 現在 [MEDIA-PLAYBACK-QUALITY] の一部として開発されている。 一部の実装は、以前の草案で記述された VideoPlaybackQuality オブジェクトと HTMLVideoElement の拡張メソッド getVideoPlaybackQuality() を 実装しているかもしれない。

B. 課題の要約

C. 参考文献

C.1 規範参照

[dom]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[FILEAPI]
File API. Marijn Kruisselbrink. W3C. 4 December 2024. W3C Working Draft. URL: https://www.w3.org/TR/FileAPI/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[MSE-REGISTRY]
Media Source Extensions™ Byte Stream Format Registry. Matthew Wolenetz; Jerry Smith; Aaron Colwell. W3C. URL: https://www.w3.org/TR/mse-byte-stream-format-registry/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/

C.2 参考(情報)

[INBANDTRACKS]
Sourcing In-band Media Resource Tracks from Media Containers into HTML. Silvia Pfeiffer; Bob Lund. W3C. 26 April 2015. Unofficial Draft. URL: https://dev.w3.org/html5/html-sourcing-inband-tracks/
[MEDIA-PLAYBACK-QUALITY]
Media Playback Quality. Mounir Lamouri; Chris Cunningham. W3C. W3C Editor's Draft. URL: https://w3c.github.io/media-playback-quality/
[url]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/