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

Conversation

davemar-bbc
Copy link
Collaborator

The new elements in BS.2076-3 - tagList and profileList - have been added. These are needed for the EBU Production Profile.
There's also a new 'parseFrame' routine to allow a S-ADM frame to be parsed without repeating the parsing of the common definitions.

@rsjbailey rsjbailey force-pushed the bs2076-3 branch 2 times, most recently from 5697cd0 to 4e5ed77 Compare April 11, 2025 11:20
Copy link
Contributor
@rsjbailey rsjbailey left a comment

Choose a reason for hiding this comment

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

Looks good, have added a few minor comments.

Only big issues are:

  • Document copying: Currently this will fail as a tag in the copy will point to the elements in the original rather than the new document. Will need to update copy.cpp to fix this. I've added a (failing) test to highlight the issue
  • Removal: Removing tagged elements from the document will result in tags pointing to elements that are no longer present. We could use weak_ptr instead of shared_ptr to hold the tag references which would solve that problem, but the tag groups themselves would then be invalid after the last reference was removed. Checking through all the tag groups every time an element is removed feels very inefficient. I guess we could store the tag groups as shared pointers on the elements rather than being owned by the tag list, and keep a weak_ptrs to the groups in the tag list, that way when the last reference to a group was removed the group would be destroyed. Downside is that it would make the setter / accessor methods for the tag group a bit more complicated. Feels like there should be a more elegant way to do it but I can't think of one right now.

Comment on lines +137 to +142
template <typename Element>
std::shared_ptr<const Element> getElement() const;

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

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?

Comment on lines +14 to +43
bool TagGroup::addReference(std::shared_ptr<AudioProgramme> programme) {
auto it =
std::find(audioProgrammes_.begin(), audioProgrammes_.end(), programme);
if (it == audioProgrammes_.end()) {
audioProgrammes_.push_back(std::move(programme));
return true;
} else {
return false;
}
}

bool TagGroup::addReference(std::shared_ptr<AudioContent> content) {
auto it = std::find(audioContents_.begin(), audioContents_.end(), content);
if (it == audioContents_.end()) {
audioContents_.push_back(std::move(content));
return true;
} else {
return false;
}
}

bool TagGroup::addReference(std::shared_ptr<AudioObject> object) {
auto it = std::find(audioObjects_.begin(), audioObjects_.end(), object);
if (it == audioObjects_.end()) {
audioObjects_.push_back(std::move(object));
return true;
} else {
return false;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

If we're storing shared_ptrs to other elements, we'll need to handle removal from the tag list when those elements are removed from the document, and pointer-resassignment during a deep copy in copy.cpp

Comment on lines +45 to +65
void TagGroup::removeReference(std::shared_ptr<AudioProgramme> programme) {
auto it =
std::find(audioProgrammes_.begin(), audioProgrammes_.end(), programme);
if (it != audioProgrammes_.end()) {
audioProgrammes_.erase(it);
}
}

void TagGroup::removeReference(std::shared_ptr<AudioContent> content) {
auto it = std::find(audioContents_.begin(), audioContents_.end(), content);
if (it != audioContents_.end()) {
audioContents_.erase(it);
}
}

void TagGroup::removeReference(std::shared_ptr<AudioObject> object) {
auto it = std::find(audioObjects_.begin(), audioObjects_.end(), object);
if (it != audioObjects_.end()) {
audioObjects_.erase(it);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Better to pass the shared_ptr<> parameters as const& here as we're not storing a copy in this function, and their atomic reference counting has a (small) cost.

Comment on lines +40 to +47
std::shared_ptr<Document> parseFrame(
std::istream& stream, const FrameHeader& header,
xml::ParserOptions options, std::shared_ptr<Document> commonDefinitions) {
xml::DocumentParser parser(stream, options, commonDefinitions);
parser.setHeader(header);
return parser.parse();
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Would be more clear if this was split out into a separate PR

Comment on lines +83 to +85
// DEBUG FUNCTIONS
int getTempId() { return temp_id_; };
void setTempId(int n) { temp_id_ = n; };
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?


std::shared_ptr<TagGroup> DocumentParser::parseTagGroup(NodePtr node) {
auto tagGroup = std::make_shared<TagGroup>();
tagGroup->setTempId(rand() % 1000);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this tempId be removed?

Comment on lines +29 to +30
class TTag : private detail::TTagBase,
private detail::AddWrapperMethods<TTag> {
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)

Comment on lines +87 to +90
template <typename... Parameters>
explicit TagGroup(Parameters... namedArgs) {
detail::setNamedOptionHelper(this, std::move(namedArgs)...);
}
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?

Comment on lines +84 to +86
ADM_EXPORT bool add(std::shared_ptr<ProfileList> profileList);
/// @brief Add a tagList
ADM_EXPORT bool add(std::shared_ptr<TagList> tagList);
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)

Comment on lines +325 to +326
std::shared_ptr<ProfileList> profileList_;
std::shared_ptr<TagList> tagList_;
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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0