From a8875cacbcbe288303138edcdec7cebe1eeabd6f Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Fri, 15 May 2026 11:57:10 +0100 Subject: [PATCH 1/2] Add AppNote describing how to find Flows to play --- docs/README.md | 1 + docs/appnotes/0023-finding-flows-to-play.md | 44 +++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 docs/appnotes/0023-finding-flows-to-play.md diff --git a/docs/README.md b/docs/README.md index c9e1d925..4e13a6be 100644 --- a/docs/README.md +++ b/docs/README.md @@ -29,6 +29,7 @@ For more information on how we use application notes, see [here](./appnotes/READ | [0020](./appnotes/0020-using-flow-profiles.md) | Using Profiles in TAMS | | [0021](./appnotes/0021-media-integrity.md) | Integrity model for media in TAMS, and when interacting with other systems | | [0022](./appnotes/0022-transform-architectures.md) | Architectures for the transforming of media | +| [0023](./appnotes/0023-finding-flows-to-play.md) | Finding Flows to Play | | [0024](./appnotes/0024-using-init-segments.md) | Using Media with Initialisation Segments in TAMS | | [0025](./appnotes/0025-editorial-purpose.md) | Editorial purpose | diff --git a/docs/appnotes/0023-finding-flows-to-play.md b/docs/appnotes/0023-finding-flows-to-play.md new file mode 100644 index 00000000..8f8c2f32 --- /dev/null +++ b/docs/appnotes/0023-finding-flows-to-play.md @@ -0,0 +1,44 @@ +# 0023: Finding Flows to Play + +## Abstract + +This describes a possible algorithm a TAMS reader or player could follow to identify the best Flow to play for a given input ID, even when multiple Flows of a Source exist. + +## Content + +In the Source/Flow model used by TAMS, most editorial processes should work in terms of Sources, relating those to specific Flow representations only when necessary. +This Application Note lays out the process a TAMS player (or a reader in general) may follow to do so. + +In general applications and components should be flexible. +The most user friendly approach tends to be accepting a single multi-essence Source (e.g. an A/V mux), locating suitable mono-essence Sources and then finding relevant Flows. +However some use cases will know exactly which Flows are required, e.g. because they have been selected by a rundown tool or MAM system. +And in some cases it will not be possible to "guess" accurately which Flows should be used. +The most flexible approach is therefore to allow both cases: accepting either a single Source, or a set of Flows. + +When given a single Source ID: + +1. `GET` the Source and check if it is multi-essence. + If not, skip to step (3). +2. Get the details of collected Sources (`GET /sources?source_collected_by_ids=`). + Choose the correct Sources to play. + 1. If there is only one of each type (e.g. one audio, one video) then these can be selected directly. + 2. Otherwise select a Source of each desired type with the lowest `priority` in the collection by default. + 3. Otherwise (or if a selected Source is multi-essence) the correct Source to play cannot be determined automatically. + Provide a suitable error to the user and insist they be specific. +3. For each selected mono-essence Source, list the Flows that represent that Source with `GET /flows?source=`. + Apply any other relevant filtering (e.g. by codec, frame size, etc.) +4. Filter the returned list of Flows to remove any that do not meet requirements, such as codecs, containers or bitrates that are not readable by this system. +5. If constructing an adaptive bitrate (ABR) ladder for a suitable player, use this list to set quality steps in the player and stop here. +6. If `generation` is present, sort the list by `generation` in ascending order. +7. If `avg_bit_rate` is present, for each Flow with the same `generation` (or every Flow if `generation` is not present), sort the list by `avg_bit_rate` in descending order. +8. Choose the entry at the top of the list as the "best available" quality. + +To read a given Flow ID, accounting for the possibility that `container_mapping` is used: + +1. `GET` the Flow and check if `container` is set. + If it is, skip to step 5, making a note of any `container_mapping` property on the Flow. +2. Check to see if the Flow is collected by a multi-essence Flow. + Examine the Flows it is collected by (using `GET /flows?flows_collected_by_id=` to find one where `container` is set +3. Examine the `collects` property of the multi-essence Flow, and check the `container_mapping` to identify which track to filter out of the multi-essence Flow. +4. Get the list of segments using `GET /flows//segments` +5. Fetch each object, filter the relevant track (if `container_mapping` is used) and then remap timing as usual From af2731046c0db95796781510d48fd0a1fc73bf20 Mon Sep 17 00:00:00 2001 From: Sam Mesterton-Gibbons Date: Mon, 24 Aug 2026 11:41:48 +0100 Subject: [PATCH 2/2] docs: Various appnote wording improvements Co-authored-by: James Sandford --- docs/appnotes/0023-finding-flows-to-play.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/appnotes/0023-finding-flows-to-play.md b/docs/appnotes/0023-finding-flows-to-play.md index 8f8c2f32..872a83a4 100644 --- a/docs/appnotes/0023-finding-flows-to-play.md +++ b/docs/appnotes/0023-finding-flows-to-play.md @@ -22,23 +22,23 @@ When given a single Source ID: 2. Get the details of collected Sources (`GET /sources?source_collected_by_ids=`). Choose the correct Sources to play. 1. If there is only one of each type (e.g. one audio, one video) then these can be selected directly. - 2. Otherwise select a Source of each desired type with the lowest `priority` in the collection by default. + 2. Otherwise select the first Source of each desired type in the order they are presented by the collection. 3. Otherwise (or if a selected Source is multi-essence) the correct Source to play cannot be determined automatically. - Provide a suitable error to the user and insist they be specific. + Fall back to manual selection by the user. 3. For each selected mono-essence Source, list the Flows that represent that Source with `GET /flows?source=`. Apply any other relevant filtering (e.g. by codec, frame size, etc.) 4. Filter the returned list of Flows to remove any that do not meet requirements, such as codecs, containers or bitrates that are not readable by this system. 5. If constructing an adaptive bitrate (ABR) ladder for a suitable player, use this list to set quality steps in the player and stop here. 6. If `generation` is present, sort the list by `generation` in ascending order. -7. If `avg_bit_rate` is present, for each Flow with the same `generation` (or every Flow if `generation` is not present), sort the list by `avg_bit_rate` in descending order. +7. Where Flows have the same `generation`, sort the list by `avg_bit_rate` in descending order (if `avg_bit_rate` is present). 8. Choose the entry at the top of the list as the "best available" quality. To read a given Flow ID, accounting for the possibility that `container_mapping` is used: 1. `GET` the Flow and check if `container` is set. - If it is, skip to step 5, making a note of any `container_mapping` property on the Flow. + If it is, skip to step 4, making a note of any `container_mapping` property on the Flow. 2. Check to see if the Flow is collected by a multi-essence Flow. - Examine the Flows it is collected by (using `GET /flows?flows_collected_by_id=` to find one where `container` is set + Examine the Flows it is collected by (using `GET /flows?collected_by_ids=` to find one where `container` is set 3. Examine the `collects` property of the multi-essence Flow, and check the `container_mapping` to identify which track to filter out of the multi-essence Flow. 4. Get the list of segments using `GET /flows//segments` 5. Fetch each object, filter the relevant track (if `container_mapping` is used) and then remap timing as usual