blob: 2125d67080806d1467e293bc52940b3c03b2cf36 [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/formats/hls/tag_name.h"
#include <utility>
#include "base/containers/fixed_flat_map.h"
#include "base/notreached.h"
#include "base/strings/string_piece.h"
namespace media::hls {
namespace {
// Ensure that tag name enums are disjoint.
template <typename A, typename B>
constexpr bool are_disjoint() {
return ToTagName(A::kMaxValue) < ToTagName(B::kMinValue) ||
ToTagName(B::kMaxValue) < ToTagName(A::kMinValue);
}
// Ensure all tag names are within the range [kMinValue, kMaxValue]
static_assert(ToTagName(CommonTagName::kMinValue) >= kMinTagName &&
ToTagName(CommonTagName::kMaxValue) <= kMaxTagName);
static_assert(ToTagName(MultivariantPlaylistTagName::kMinValue) >=
kMinTagName &&
ToTagName(MultivariantPlaylistTagName::kMaxValue) <= kMaxTagName);
static_assert(ToTagName(MediaPlaylistTagName::kMinValue) >= kMinTagName &&
ToTagName(MediaPlaylistTagName::kMaxValue) <= kMaxTagName);
// Ensure tag name sets are contiguous
static_assert(ToTagName(MultivariantPlaylistTagName::kMinValue) ==
ToTagName(CommonTagName::kMaxValue) + 1);
static_assert(ToTagName(MediaPlaylistTagName::kMinValue) ==
ToTagName(MultivariantPlaylistTagName::kMaxValue) + 1);
// Ensure tag name sets are non-overlapping
static_assert(are_disjoint<CommonTagName, MultivariantPlaylistTagName>());
static_assert(are_disjoint<CommonTagName, MediaPlaylistTagName>());
static_assert(
are_disjoint<MultivariantPlaylistTagName, MediaPlaylistTagName>());
template <typename T>
constexpr std::pair<base::StringPiece, TagName> TagNameEntry(
base::StringPiece name_str,
T name) {
return std::make_pair(name_str, ToTagName(name));
}
// Mapping of tag names to their constants. This must remain sorted by the
// string value.
constexpr auto kTagNames = base::MakeFixedFlatMap({
TagNameEntry("EXT-X-CONTENT-STEERING",
MultivariantPlaylistTagName::kXContentSteering),
TagNameEntry("EXT-X-DEFINE", CommonTagName::kXDefine),
TagNameEntry("EXT-X-DISCONTINUITY", MediaPlaylistTagName::kXDiscontinuity),
TagNameEntry("EXT-X-END-LIST", MediaPlaylistTagName::kXEndList),
TagNameEntry("EXT-X-GAP", MediaPlaylistTagName::kXGap),
TagNameEntry("EXT-X-I-FRAME-STREAM-INF",
MultivariantPlaylistTagName::kXIFrameStreamInf),
TagNameEntry("EXT-X-I-FRAMES-ONLY", MediaPlaylistTagName::kXIFramesOnly),
TagNameEntry("EXT-X-INDEPENDENT-SEGMENTS",
CommonTagName::kXIndependentSegments),
TagNameEntry("EXT-X-MEDIA", MultivariantPlaylistTagName::kXMedia),
TagNameEntry("EXT-X-PLAYLIST-TYPE", MediaPlaylistTagName::kXPlaylistType),
TagNameEntry("EXT-X-SESSION-DATA",
MultivariantPlaylistTagName::kXSessionData),
TagNameEntry("EXT-X-SESSION-KEY",
MultivariantPlaylistTagName::kXSessionKey),
TagNameEntry("EXT-X-STREAM-INF", MultivariantPlaylistTagName::kXStreamInf),
TagNameEntry("EXT-X-VERSION", CommonTagName::kXVersion),
TagNameEntry("EXTINF", MediaPlaylistTagName::kInf),
TagNameEntry("EXTM3U", CommonTagName::kM3u),
});
// `kTagNames` must cover the entire [kMinTagName, kMaxTagName] range.
static_assert(kTagNames.size() ==
static_cast<size_t>(kMaxTagName - kMinTagName + 1));
} // namespace
TagKind GetTagKind(TagName name) {
if (name <= ToTagName(CommonTagName::kMaxValue)) {
return TagKind::kCommonTag;
}
if (name <= ToTagName(MultivariantPlaylistTagName::kMaxValue)) {
return TagKind::kMultivariantPlaylistTag;
}
if (name <= ToTagName(MediaPlaylistTagName::kMaxValue)) {
return TagKind::kMediaPlaylistTag;
}
NOTREACHED();
return TagKind::kMaxValue;
}
absl::optional<TagName> ParseTagName(base::StringPiece name) {
// Search for the tag name
const auto* match = kTagNames.find(name);
if (match == kTagNames.end()) {
return absl::nullopt;
}
return match->second;
}
base::StringPiece TagNameToString(TagName name) {
for (auto entry : kTagNames) {
if (name == entry.second) {
return entry.first;
}
}
NOTREACHED();
return "";
}
} // namespace media::hls