Dynamic audio stream switching is currently a Netflix specific requirement to allow a new audio track to be selected whilst streaming is on progress with minimal disruption to the users viewing experience (no more than a short audio dropout). The new audio track may use a different codec to the previous one. The current implementation relies on platform specific implementations of the performAudioTrackCodecChannelSwitch_soc() API but it would be desirable in future to implement a platform agnostic solution for this.
@startuml autonumber box "Container" #LightGreen participant Netflix participant "DPI\n(IElementaryStreamAudioPlayer)" as DPI participant GStreamer_client participant rialtoClient end box box "Platform" #LightBlue participant rialtoServer participant rdk_gstreamer_utils end box note across disable()/flush()/enable()/firstSampleAvailable() call sequence is guaranteed by Netflix but is only used to detect that an audio stream switch has been initiated in DPI implementation. end note Netflix -> DPI: disable() DPI --> Netflix: Netflix -> DPI: flush() DPI -> DPI: Set audio_switch flag DPI --> Netflix: Netflix -> DPI: enable() DPI --> Netflix: Netflix -> DPI: firstSampleAvailable() DPI --> Netflix: DPI --/ Netflix: getNextMediaSample() Netflix -> DPI: write(sample) note right: ISampleWriter detail skipped for clarity opt audio_switch flag set DPI -> DPI: clear audio_switch flag DPI -> GStreamer_client: performAudioTrackCodecChannelSwitch(audioAttr, caps, ...) note right: This will be a custom Rialto implementation of the API GStreamer_client -> rialtoClient: flush(current_audio_src_id) rialtoClient -> rialtoServer: flush(current_audio_src_id) rialtoServer -> rialtoServer: flush note right: Flush procedure described in Flush diagram rialtoServer --> rialtoClient: rialtoClient --> GStreamer_client: GStreamer_client -> GStreamer_client: Convert audioAttr & caps to rialto::mediaSource GStreamer_client -> rialtoClient: switchSource(mediaSource) rialtoClient -> rialtoServer: switchSource(mediaSource) opt audio caps changed rialtoServer -> rdk_gstreamer_utils: performAudioTrackCodecChannelSwitch(audioAttr, caps, ...) note right: This will call the underlying _soc\nimplementation for the platform rdk_gstreamer_utils --> rialtoServer: end rialtoServer --> rialtoClient: rialtoClient --> GStreamer_client: GStreamer_client --> DPI: DPI --> Netflix: end @enduml |
The removeSource() & remove Source implementations are as shown in the above diagram, the only difference is how they are triggered from DPI.
@startuml autonumber box "Container" #LightGreen participant Netflix participant "DPI\n(IElementaryStreamAudioPlayer)" as DPI participant rialtoClient end box Netflix -> DPI: disable() DPI --> Netflix: Netflix -> DPI: flush() DPI -> rialtoClient: removeSource(current_audio_src_id) rialtoClient --> DPI: DPI --> Netflix: Netflix -> DPI: enable() DPI --> Netflix: Netflix -> DPI: firstSampleAvailable() DPI --> Netflix: opt First media sample after firstSampleAvailable() called DPI --/ Netflix: getNextMediaSample() Netflix -> DPI: write(sample) note right: ISampleWriter detail skipped for clarity DPI -> DPI: Convert sample info to rialto::mediaSource DPI -> rialtoClient: attachSource(mediaSource) rialtoClient --> DPI: DPI --> Netflix: end @enduml |