8000 New BS.2076-3 features (tagList, profileList). by davemar-bbc · Pull Request #201 · ebu/libadm · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

New BS.2076-3 features (tagList, profileList). #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions include/adm/document.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ namespace adm {
ADM_EXPORT bool add(std::shared_ptr<AudioTrackFormat> trackFormat);
/// @brief Add an AudioTrackUid
ADM_EXPORT bool add(std::shared_ptr<AudioTrackUid> trackUid);
/// @brief Add a profileList
ADM_EXPORT bool add(std::shared_ptr<ProfileList> profileList);
/// @brief Add a tagList
ADM_EXPORT bool add(std::shared_ptr<TagList> tagList);
Comment on lines +84 to +86
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these should be set()? (you can't have >1 profileList or tagList in a document)

///@}

/** @name Remove ADM elements
Expand All @@ -104,6 +108,10 @@ namespace adm {
ADM_EXPORT bool remove(std::shared_ptr<AudioTrackFormat> trackFormat);
/// @brief Remove an AudioTrackUid
ADM_EXPORT bool remove(std::shared_ptr<AudioTrackUid> trackUid);
/// @brief Remove a profileList
ADM_EXPORT bool remove(std::shared_ptr<ProfileList> profileList);
/// @brief Remove a tagList
ADM_EXPORT bool remove(std::shared_ptr<TagList> tagList);
///@}

/**
Expand All @@ -126,6 +134,12 @@ namespace adm {
template <typename Element>
ElementRange<Element> getElements();

template <typename Element>
std::shared_ptr<const Element> getElement() const;

template <typename Element>
std::shared_ptr<Element> getElement();

Comment on lines +137 to +142
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm missing something specific about TagList and ProfileList, I'd be a bit inclined to remove getElement(), and instead add TagList and ProfileList to DocumentBase as OptionalElements - Partly for consistency with the rest of the API when retreiving individual sub elements (everywhere else uses get<T>()), partly so you get the usual has/get/set/isDefault behaviour for free. I think if we kept things as-it, a 2076-2 or below document would just return nullptr, which I don't think we do anywhere else to indicate an absence?

/** @name Lookup ADM elements by its Id
*
* Lookup the first ADM element with the given Id.
Expand Down Expand Up @@ -257,6 +271,10 @@ namespace adm {
detail::ParameterTraits<AudioTrackFormat>::tag) const;
ADM_EXPORT ElementRange<const AudioTrackUid> getElements(
detail::ParameterTraits<AudioTrackUid>::tag) const;
ADM_EXPORT std::shared_ptr<const ProfileList> getElement(
detail::ParameterTraits<ProfileList>::tag) const;
ADM_EXPORT std::shared_ptr<const TagList> getElement(
detail::ParameterTraits<TagList>::tag) const;
ADM_EXPORT ElementRange<AudioProgramme> getElements(
detail::ParameterTraits<AudioProgramme>::tag);
ADM_EXPORT ElementRange<AudioContent> getElements(
Expand All @@ -273,6 +291,10 @@ namespace adm {
detail::ParameterTraits<AudioTrackFormat>::tag);
ADM_EXPORT ElementRange<AudioTrackUid> getElements(
detail::ParameterTraits<AudioTrackUid>::tag);
ADM_EXPORT std::shared_ptr<ProfileList> getElement(
detail::ParameterTraits<ProfileList>::tag);
ADM_EXPORT std::shared_ptr<TagList> getElement(
detail::ParameterTraits<TagList>::tag);

/// check the parent of an element
///
Expand Down Expand Up @@ -300,6 +322,8 @@ namespace adm {
std::vector<std::shared_ptr<AudioStreamFormat>> audioStreamFormats_;
std::vector<std::shared_ptr<AudioTrackFormat>> audioTrackFormats_;
std::vector<std::shared_ptr<AudioTrackUid>> audioTrackUids_;
std::shared_ptr<ProfileList> profileList_;
std::shared_ptr<TagList> tagList_;
Comment on lines +325 to +326
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These probably want to be boost::optional<> rather than std::shared_ptr<> as we don't need reference semantics I don't think, just the ability for the elements to not be present?

detail::IdAssigner idAssigner_;
};

Expand All @@ -317,4 +341,16 @@ namespace adm {
return getElements(Tag());
}

template <typename Element>
std::shared_ptr<const Element> Document::getElement() const {
typedef typename detail::ParameterTraits<Element>::tag Tag;
return getElement(Tag());
}

template <typename Element>
std::shared_ptr<Element> Document::getElement() {
typedef typename detail::ParameterTraits<Element>::tag Tag;
return getElement(Tag());
}

} // namespace adm
1 change: 1 addition & 0 deletions include/adm/elements.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "adm/elements/audio_stream_format.hpp"
#include "adm/elements/audio_track_uid.hpp"
#include "adm/elements/profile_list.hpp"
#include "adm/elements/tag_list.hpp"

#include "adm/elements/audio_block_format_direct_speakers.hpp"
#include "adm/elements/audio_block_format_matrix.hpp"
Expand Down
2 changes: 1 addition & 1 deletion include/adm/elements/audio_channel_format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ namespace adm {
return previous == 0u || current == previous.get() + 1u;
}
}

template <typename BlockFormat>
void AudioChannelFormat::assignId(BlockFormat &blockFormat,
BlockFormat *previousBlock) {
Expand Down
4 changes: 2 additions & 2 deletions include/adm/elements/profile_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ namespace adm {
using ProfileListBase = HasParameters<VectorParameter<Profiles>>;
} // namespace detail

struct ProfileceListTag {};
struct ProfileListTag {};

class ProfileList : private detail::ProfileListBase,
private detail::AddWrapperMethods<ProfileList> {
public:
using tag = ProfileceListTag;
using tag = ProfileListTag;

template <typename... Parameters>
explicit ProfileList(Parameters... namedArgs) {
Expand Down
258 changes: 258 additions & 0 deletions include/adm/elements/tag_list.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
#pragma once
#include <vector>
#include "adm/detail/auto_base.hpp"
#include "adm/elements/audio_programme.hpp"
#include "adm/elements_fwd.hpp"
#include "adm/detail/named_option_helper.hpp"
#include "adm/detail/optional_comparison.hpp"
#include "adm/errors.hpp"

namespace adm {
struct TTagValueTag {};
using TTagValue = detail::NamedType<std::string, TTagValueTag>;

struct TTagClassTag {};
F438 using TTagClass = detail::NamedType<std::string, TTagClassTag>;

struct TTagTag {};

namespace detail {
extern template class ADM_EXPORT_TEMPLATE_METHODS
RequiredParameter<TTagValue>;
extern template class ADM_EXPORT_TEMPLATE_METHODS
OptionalParameter<TTagClass>;

using TTagBase = HasParameters<RequiredParameter<TTagValue>,
OptionalParameter<TTagClass>>;
} // namespace detail

class TTag : private detail::TTagBase,
private detail::AddWrapperMethods<TTag> {
Comment on lines +29 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we not just call these Tag, TagValue TagClass? You can tell from context that they're associated with the TagGroup (i.e. they only ever appear in methods associated with the tag group)

public:
using tag = TTagTag;

template <typename... Parameters>
explicit TTag(Parameters... namedArgs) {
detail::setNamedOptionHelper(this, std::move(namedArgs)...);
}

ADM_EXPORT explicit TTag(std::string str)
: TTag(TTagValue(std::move(str))) {}
ADM_EXPORT explicit TTag(const char *s);

ADM_EXPORT void print(std::ostream &os) const;

using detail::TTagBase::set;
using detail::TTagBase::unset;
using detail::AddWrapperMethods<TTag>::get;
using detail::AddWrapperMethods<TTag>::has;
using detail::AddWrapperMethods<TTag>::isDefault;
using detail::AddWrapperMethods<TTag>::unset;

private:
using detail::TTagBase::get;
using detail::TTagBase::has;

friend class detail::AddWrapperMethods<TTag>;
};

struct TTagsTag {};

using TTags = std::vector<TTag>;
ADD_TRAIT(TTags, TTagsTag);

inline bool operator==(const TTag &a, const TTag &b) {
return detail::optionalsEqual<TTagValue, TTagClass>(a, b);
}

inline bool operator!=(const TTag &a, const TTag &b) { return !(a == b); }

struct TagGroupTag {};

namespace detail {
extern template class ADM_EXPORT_TEMPLATE_METHODS VectorParameter<TTags>;

using TagGroupBase = HasParameters<VectorParameter<TTags>>;
} // namespace detail

class TagGroup : private detail::TagGroupBase,
private detail::AddWrapperMethods<TagGroup> {
public:
using tag = TagGroupTag;

// DEBUG FUNCTIONS
int getTempId() { return temp_id_; };
void setTempId(int n) { temp_id_ = n; };
Comment on lines +83 to +85
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these be removed?


template <typename... Parameters>
explicit TagGroup(Parameters... namedArgs) {
detail::setNamedOptionHelper(this, std::move(namedArgs)...);
}
Comment on lines +87 to +90
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the spec says there must be at least one reference associated with a tag group, so it'd be good to enforce that as an invariant. I think you could do that by making 3 constructors:

template<typename... Parameters>
explicit TagGroup(std::shared_ptr<AudioObject> const& reference, Parameters... namedArgs);
template<typename... Parameters>
explicit TagGroup(std::shared_ptr<AudioContent> const& reference, Parameters... namedArgs);
template<typename... Parameters>
explicit TagGroup(std::shared_ptr<AudioProgramme> const& reference, Parameters... namedArgs);

And then making tag groups immutable. Alternatively you could make removing the last reference throw but that feels messier? What do you think?


/// @brief Add reference to an AudioProgramme
ADM_EXPORT bool addReference(std::shared_ptr<AudioProgramme> programme);

/// @brief Add reference to an AudioContent
ADM_EXPORT bool addReference(std::shared_ptr<AudioContent> content);

/// @brief Add reference to an AudioObject
ADM_EXPORT bool addReference(std::shared_ptr<AudioObject> object);

template <typename Element>
ElementRange<Element> getReferences();

template <typename Element>
ElementRange<const Element> getReferences() const;

/// @brief Remove reference to an AudioProgramme
ADM_EXPORT void removeReference(std::shared_ptr<AudioProgramme> programme);

/// @brief Remove reference to an AudioContent
ADM_EXPORT void removeReference(std::shared_ptr<AudioContent> content);

/// @brief Remove reference to an AudioObject
ADM_EXPORT void removeReference(std::shared_ptr<AudioObject> object);

template <typename Element>
void clearReferences();

using detail::TagGroupBase::set;
using detail::AddWrapperMethods<TagGroup>::get;
using detail::AddWrapperMethods<TagGroup>::has;
using detail::AddWrapperMethods<TagGroup>::isDefault;
using detail::AddWrapperMethods<TagGroup>::unset;
using detail::TagGroupBase::add;
using detail::TagGroupBase::remove;

private:
int temp_id_;

using detail::TagGroupBase::get;
using detail::TagGroupBase::has;
using detail::TagGroupBase::isDefault;
using detail::TagGroupBase::unset;

friend class detail::AddWrapperMethods<TagGroup>;

ADM_EXPORT ElementRange<const AudioProgramme> getReferences(
detail::ParameterTraits<AudioProgramme>::tag) const;
ADM_EXPORT ElementRange<AudioProgramme> getReferences(
detail::ParameterTraits<AudioProgramme>::tag);
ADM_EXPORT ElementRange<const AudioContent> getReferences(
detail::ParameterTraits<AudioContent>::tag) const;
ADM_EXPORT ElementRange<AudioContent> getReferences(
detail::ParameterTraits<AudioContent>::tag);
ADM_EXPORT ElementRange<const AudioObject> getReferences(
detail::ParameterTraits<AudioObject>::tag) const;
ADM_EXPORT ElementRange<AudioObject> getReferences(
detail::ParameterTraits<AudioObject>::tag);

ADM_EXPORT void clearReferences(
detail::ParameterTraits<AudioProgramme>::tag);
ADM_EXPORT void clearReferences(detail::ParameterTraits<AudioContent>::tag);
ADM_EXPORT void clearReferences(detail::ParameterTraits<AudioObject>::tag);

ADM_EXPORT void disconnectReferences();

std::vector<std::shared_ptr<AudioProgramme>> audioProgrammes_;
std::vector<std::shared_ptr<AudioContent>> audioContents_;
std::vector<std::shared_ptr<AudioObject>> audioObjects_;
};

inline bool operator==(const TagGroup &a, const TagGroup &b) {
return detail::optionalsEqual<TTags>(a, b);
}

inline bool operator!=(const TagGroup &a, const TagGroup &b) {
return !(a == b);
}

template <typename Element>
ElementRange<const Element> TagGroup::getReferences() const {
typedef typename detail::ParameterTraits<Element>::tag Tag;
return getReferences(Tag());
}

template <typename Element>
ElementRange<Element> TagGroup::getReferences() {
typedef typename detail::ParameterTraits<Element>::tag Tag;
return getReferences(Tag());
}

inline ElementRange<const AudioProgramme> TagGroup::getReferences(
detail::ParameterTraits<AudioProgramme>::tag) const {
return detail::makeElementRange<AudioProgramme>(audioProgrammes_);
}

inline ElementRange<AudioProgramme> TagGroup::getReferences(
detail::ParameterTraits<AudioProgramme>::tag) {
return detail::makeElementRange<AudioProgramme>(audioProgrammes_);
}

inline ElementRange<const AudioContent> TagGroup::getReferences(
detail::ParameterTraits<AudioContent>::tag) const {
return detail::makeElementRange<AudioContent>(audioContents_);
}

inline ElementRange<AudioContent> TagGroup::getReferences(
detail::ParameterTraits<AudioContent>::tag) {
return detail::makeElementRange<AudioContent>(audioContents_);
}

inline ElementRange<const AudioObject> TagGroup::getReferences(
detail::ParameterTraits<AudioObject>::tag) const {
return detail::makeElementRange<AudioObject>(audioObjects_);
}

inline ElementRange<AudioObject> TagGroup::getReferences(
detail::ParameterTraits<AudioObject>::tag) {
return detail::makeElementRange<AudioObject>(audioObjects_);
}

template <typename Element>
void TagGroup::clearReferences() {
typedef typename detail::ParameterTraits<Element>::tag Tag;
clearReferences(Tag());
}

struct TagGroupsTag {};

using TagGroups = std::vector<TagGroup>;
ADD_TRAIT(TagGroups, TagGroupsTag);

namespace detail {
extern template class ADM_EXPORT_TEMPLATE_METHODS
VectorParameter<TagGroups>;

using TagListBase = HasParameters<VectorParameter<TagGroups>>;
} // namespace detail

struct TagListTag {};

class TagList : private detail::TagListBase,
private detail::AddWrapperMethods<TagList> {
public:
using tag = TagListTag;

template <typename... Parameters>
explicit TagList(Parameters... namedArgs) {
detail::setNamedOptionHelper(this, std::move(namedArgs)...);
}

using detail::TagListBase::set;
using detail::AddWrapperMethods<TagList>::get;
using detail::AddWrapperMethods<TagList>::has;
using detail::AddWrapperMethods<TagList>::isDefault;
using detail::AddWrapperMethods<TagList>::unset;
using detail::TagListBase::add;
using detail::TagListBase::remove;

private:
using detail::TagListBase::get;
using detail::TagListBase::has;
using detail::TagListBase::isDefault;
using detail::TagListBase::unset;

friend class detail::AddWrapperMethods<TagList>;
};
} // namespace adm
15 changes: 15 additions & 0 deletions include/adm/parse.hpp
< 64E5 td id="diff-f9876b2c39f542719f4214bee0a781e947b6fd8628341b79f11b705f779fcb3eR102" data-line-number="102" class="blob-num blob-num-addition js-linkable-line-number js-blob-rnum">
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ namespace adm {
std::istream& stream, FrameHeader const& header,
xml::ParserOptions options = xml::ParserOptions::none);

/**
* @brief Parse an xml frame containing an audioFormatExtended
* node into an adm::Document, using a SADM FrameHeader to check for consistency.
* Primarily intended for parsing sadm frames.
*
* Parse adm data from an `std::istream`.
* @param stream input stream to parse XML data
* @param header S-ADM Frame header
* @param options Options to influence the XML parser behaviour
* @param commonDefinitions Common Defintions document
*/
ADM_EXPORT std::shared_ptr<Document> parseFrame(
std::istream& stream, const FrameHeader& header,
xml::ParserOptions options, std::shared_ptr<Document> commonDefinitions);

/**
* @brief Parse an XML representation of a serial ADM frame and return
* the frameHeader element as an adm::FrameHeader object
Expand Down
Loading
Loading
0