Design

Architecture diagram

digraph shaka_packager {
  label=<<u>Shaka Packager Architecture</u>>
  labelloc=t

  subgraph cluster_media {
    label=<<u>Media Processing Pipeline</u>>

    Demuxer, ChunkingHandler, EncryptionHandler, Replicator,
        TrickplayHandler, Muxer [shape=rectangle]

    Demuxer -> ChunkingHandler [style=bold headlabel="many" taillabel="1"]
    ChunkingHandler -> EncryptionHandler -> Replicator -> TrickplayHandler
        -> Muxer [style=bold]
    ChunkingHandler -> Replicator -> Muxer [style=bold]

    subgraph cluster_demuxer {
      style=rounded
      label=<<u> </u>>

      Demuxer2 [label="Demuxer" shape=rectangle]
      Demuxer2 -> MediaParser
          [dir=back arrowtail=diamond headlabel="1" taillabel="1"]
      MediaParser -> Mp4MediaParser, WebMMediaParser, Mp2tMediaParser,
          WvmMediaParser [dir=back arrowtail=onormal]
    }

    subgraph cluster_muxer {
      style=rounded
      label=<<u> </u>>

      Muxer2 [label="Muxer" shape=rectangle]
      Muxer2 -> Mp4Muxer, WebMMuxer, Mp2tMuxer [dir=back arrowtail=onormal]
    }

    # Hack to place cluster_muxer subgraph below cluster_demuxer subgraph.
    WebMMediaParser, Mp2tMediaParser -> Muxer2
      [style=invisible arrowhead=none]
  }

  MuxerListener, MpdNotifyMuxerListener, HlsNotifyMuxerListener,
      MpdNotifier, HlsNotifier [shape=rectangle style=rounded]

  Muxer -> MuxerListener
  MuxerListener -> MpdNotifyMuxerListener, HlsNotifyMuxerListener
      [dir=back arrowtail=onormal]

  subgraph cluster_manifest {
    label=<<u>Manifest Generation</u>>

    HlsNotifyMuxerListener -> HlsNotifier [headlabel="1" taillabel="many"]
    MpdNotifyMuxerListener -> MpdNotifier [headlabel="1" taillabel="many"]

    MasterPlaylist, MediaPlaylist, MpdBuilder, AdaptationSet,
        Representation [shape=trapezium]

    HlsNotifier -> MasterPlaylist
    MasterPlaylist -> MediaPlaylist
        [dir=back arrowtail=diamond headlabel="many" taillabel="1"]
    MpdNotifier -> MpdBuilder
    MpdBuilder -> AdaptationSet -> Representation
        [dir=back arrowtail=diamond headlabel="many" taillabel="1"]

    {rank=same; MasterPlaylist, MpdBuilder}
    {rank=same; MediaPlaylist, Representation}
  }

  subgraph cluster_legend {
    style=rounded
    label=<<u>Legend</u>>

    node [shape=plaintext]

    blank1 [label="" height=0]
    blank2 [label="" height=0]
    blank3 [label="" height=0]

    "Composition" -> blank1 [dir=back arrowtail=diamond]
    "Inheritance" -> blank2 [dir=back arrowtail=onormal]
    "MediaHandler data flow" -> blank3 [style=bold]

    "Bridge Class" [shape=rectangle style=rounded]
    "Manifest Class" [shape=trapezium]
    MediaHandler [shape=rectangle]
  }

  # Hack to place legend subgraph in the bottom.
  MediaPlaylist -> MediaHandler [style=invisible arrowhead=none]
}

Media handler data flow

digraph g {
  rankdir=LR

  StreamData [
    label="{... | SegmentInfo | MediaSample ... | SegmentInfo | MediaSample ... | StreamInfo}"
    shape=record
    style=rounded
  ];

  MediaHandler [shape=rectangle]
  MediaHandler2 [shape=rectangle, label=MediaHandler]
  MediaHandler -> StreamData -> MediaHandler2
}

MediaHandler -> MediaHandler2 : StreamInfo
MediaHandler -> MediaHandler2 : MediaSample
MediaHandler -> MediaHandler2 : MediaSample
MediaHandler -> MediaHandler2 : ...
MediaHandler -> MediaHandler2 : MediaSample
MediaHandler -> MediaHandler2 : SegmentInfo
MediaHandler -> MediaHandler2 : MediaSample
MediaHandler -> MediaHandler2 : MediaSample
MediaHandler -> MediaHandler2 : ...
MediaHandler -> MediaHandler2 : MediaSample
MediaHandler -> MediaHandler2 : SegmentInfo
MediaHandler -> MediaHandler2 : ...

Demuxer

digraph g {
  rankdir=LR

  StreamData [
    label="{MediaSample ... | StreamInfo}", shape=record, style=rounded
  ]
  StreamData2 [
    label="{MediaSample ... | StreamInfo}", shape=record, style=rounded
  ]

  Demuxer [shape=rectangle]
  Demuxer -> StreamData
  Demuxer -> StreamData2
}

Demuxer -> : StreamInfo
Demuxer -> : MediaSample
Demuxer -> : MediaSample
Demuxer -> : ...

ChunkingHandler

digraph g {
  rankdir=LR

  StreamDataIn [
    label="{MediaSample ... | StreamInfo}", shape=record, style=rounded
  ]
  StreamDataOut [
    label="{SegmentInfo | MediaSample ... | StreamInfo}"
    shape=record
    style=rounded
  ]

  ChunkingHandler [shape=rectangle]
  StreamDataIn -> ChunkingHandler -> StreamDataOut
}

-> ChunkingHandler : StreamInfo
ChunkingHandler -> : StreamInfo
-> ChunkingHandler : MediaSample
ChunkingHandler -> : MediaSample
-> ChunkingHandler : ...
ChunkingHandler -> : ...
-> ChunkingHandler : MediaSample
ChunkingHandler -> : MediaSample
ChunkingHandler -> : SegmentInfo
-> ChunkingHandler : ...
ChunkingHandler -> : ...

Manifest generation event flow

DASH On Demand

alt stream is encrypted
Muxer -> MuxerListener : OnEncryptionInfoReady
MuxerListener -> MuxerListener : Cache EncryptionInfo
end

Muxer -> MuxerListener : OnMediaStart
MuxerListener -> MuxerListener : Cache MediaInfo

alt segment is not encrypted
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> MuxerListener : Cache SegmentInfo
Muxer -> MuxerListener : OnNewSegment N-1
MuxerListener -> MuxerListener : Cache SegmentInfo
end

alt segment is encrypted
Muxer -> MuxerListener : OnEncryptionStart
Muxer -> MuxerListener : OnNewSegment N
MuxerListener -> MuxerListener : Cache SegmentInfo
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> MuxerListener : Cache SegmentInfo
alt encryption key changes
Muxer -> MuxerListener : OnEncryptionInfoReady
MuxerListener -> MpdNotifier : NotifyEncryptionUpdate
Muxer -> MuxerListener : OnNewSegment N+k
MuxerListener -> MuxerListener : Cache SegmentInfo
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> MuxerListener : Cache SegmentInfo
end
end

Muxer -> MuxerListener : OnMediaEnd

MuxerListener -> MpdNotifier : NotifyNewContainer
MuxerListener -> MpdNotifier : NotifyNewSegment ...
MuxerListener -> MpdNotifier : NotifyNewSegment N
MuxerListener -> MpdNotifier : NotifyNewSegment N+1
MuxerListener -> MpdNotifier : NotifyNewSegment ...
MuxerListener -> MpdNotifier : Flush

DASH Live

alt stream is encrypted
Muxer -> MuxerListener : OnEncryptionInfoReady
MuxerListener -> MuxerListener : Cache EncryptionInfo
end

Muxer -> MuxerListener : OnMediaStart
MuxerListener -> MpdNotifier : NotifyNewContainer

alt segment is not encrypted
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> MpdNotifier : NotifyNewSegment ...
Muxer -> MuxerListener : OnNewSegment N-1
MuxerListener -> MpdNotifier : NotifyNewSegment N-1
end

alt segment is encrypted
Muxer -> MuxerListener : OnEncryptionStart
Muxer -> MuxerListener : OnNewSegment N
MuxerListener -> MpdNotifier : NotifyNewSegment N
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> MpdNotifier : NotifyNewSegment ...
alt encryption key changes
Muxer -> MuxerListener : OnEncryptionInfoReady
MuxerListener -> MpdNotifier : NotifyEncryptionUpdate
Muxer -> MuxerListener : OnNewSegment N+k
MuxerListener -> MpdNotifier : NotifyNewSegment N+k
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> MpdNotifier : NotifyNewSegment ...
end
end

Muxer -> MuxerListener : OnMediaEnd
MuxerListener -> MpdNotifier : Flush

HLS Single-segment

alt stream is encrypted
Muxer -> MuxerListener : OnEncryptionInfoReady
MuxerListener -> MuxerListener : Cache EncryptionInfo
end

Muxer -> MuxerListener : OnMediaStart
MuxerListener -> MuxerListener : Cache MediaInfo

alt segment is not encrypted
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> MuxerListener : Cache SegmentInfo
Muxer -> MuxerListener : OnNewSegment N-1
MuxerListener -> MuxerListener : Cache SegmentInfo
end

alt segment is encrypted
Muxer -> MuxerListener : OnEncryptionStart
Muxer -> MuxerListener : OnNewSegment N
MuxerListener -> MuxerListener : Cache SegmentInfo
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> MuxerListener : Cache SegmentInfo
alt encryption key changes
Muxer -> MuxerListener : OnEncryptionInfoReady
MuxerListener -> HlsNotifier : Cache EncryptionInfo
Muxer -> MuxerListener : OnNewSegment N+k
MuxerListener -> MuxerListener : Cache SegmentInfo
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> MuxerListener : Cache SegmentInfo
end
end

Muxer -> MuxerListener : OnMediaEnd

MuxerListener -> HlsNotifier : NotifyNewStream
alt stream is encrypted
MuxerListener -> HlsNotifier : NotifyEncryptionUpdate
end
MuxerListener -> HlsNotifier : NotifyNewSegment ...
MuxerListener -> HlsNotifier : NotifyNewSegment N
MuxerListener -> HlsNotifier : NotifyNewSegment N+1
MuxerListener -> HlsNotifier : NotifyNewSegment ...

HLS Multi-segment

alt stream is encrypted
Muxer -> MuxerListener : OnEncryptionInfoReady
MuxerListener -> MuxerListener : Cache EncryptionInfo
end

Muxer -> MuxerListener : OnMediaStart
MuxerListener -> HlsNotifier : NotifyNewStream

alt segment is not encrypted
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> HlsNotifier : NotifyNewSegment ...
Muxer -> MuxerListener : OnNewSegment N-1
MuxerListener -> HlsNotifier : NotifyNewSegment N-1
end

alt segment is encrypted
Muxer -> MuxerListener : OnEncryptionStart
MuxerListener -> HlsNotifier : NotifyEncryptionUpdate
Muxer -> MuxerListener : OnNewSegment N
MuxerListener -> HlsNotifier : NotifyNewSegment N
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> HlsNotifier : NotifyNewSegment ...
alt encryption key changes
Muxer -> MuxerListener : OnEncryptionInfoReady
MuxerListener -> HlsNotifier : NotifyEncryptionUpdate
Muxer -> MuxerListener : OnNewSegment N+k
MuxerListener -> HlsNotifier : NotifyNewSegment N+k
Muxer -> MuxerListener : OnNewSegment ...
MuxerListener -> HlsNotifier : NotifyNewSegment ...
end
end

Muxer -> MuxerListener : OnMediaEnd