| /* |
| * Copyright (c) 2024 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #ifndef MEDIA_BASE_CODEC_LIST_H_ |
| #define MEDIA_BASE_CODEC_LIST_H_ |
| |
| #include <cstddef> |
| #include <span> |
| #include <vector> |
| |
| #include "api/rtc_error.h" |
| #include "media/base/codec.h" |
| |
| namespace webrtc { |
| |
| class CodecList { |
| public: |
| using iterator = std::vector<Codec>::iterator; |
| using const_iterator = std::vector<Codec>::const_iterator; |
| using value_type = Codec; |
| |
| CodecList() = default; |
| // Copy and assign are available. |
| CodecList(const CodecList&) = default; |
| CodecList& operator=(const CodecList&) = default; |
| CodecList(CodecList&&) = default; |
| CodecList& operator=(CodecList&&) = default; |
| bool operator==(const CodecList& o) const { return codecs_ == o.codecs_; } |
| |
| // Creates a codec list on untrusted data. If successful, the |
| // resulting CodecList satisfies all the CodecList invariants. |
| static RTCErrorOr<CodecList> Create(std::span<const Codec> codecs); |
| // Creates a codec list on trusted data. Only for use when |
| // the codec list is generated from internal code. |
| static CodecList CreateFromTrustedData(std::span<const Codec> codecs) { |
| return CodecList(codecs); |
| } |
| // The outcome of PushIfNotPresent(). |
| enum class PushResult { |
| // The codec was added to the list. |
| kInserted, |
| // The exact same codec was already in the list; the list is unchanged. |
| kDuplicate, |
| // A different codec with the same payload type was already in the list. |
| // The list is unchanged and an error is logged. This means that the |
| // caller combined codecs that come from different payload type mappings, |
| // which is a programming error. |
| kConflict, |
| }; |
| |
| // Inserts a codec into the list if no codec with the same payload type is |
| // present. The payload types in the list are kept unique; the codec that is |
| // already in the list is never replaced. |
| [[nodiscard]] PushResult PushIfNotPresent(const Codec& codec); |
| |
| // Vector-compatible API to access the codecs. |
| iterator begin() { return codecs_.begin(); } |
| iterator end() { return codecs_.end(); } |
| const_iterator begin() const { return codecs_.begin(); } |
| const_iterator end() const { return codecs_.end(); } |
| const Codec& operator[](size_t i) const { return codecs_[i]; } |
| Codec& operator[](size_t i) { return codecs_[i]; } |
| // Appends a codec to the list. Payload types must remain unique. Note that |
| // an RTX codec may be added before the codec that it refers to, so the check |
| // that referenced codecs exist is left to CheckConsistency(). |
| void push_back(const Codec& codec); |
| bool empty() const { return codecs_.empty(); } |
| void clear() { codecs_.clear(); } |
| size_t size() const { return codecs_.size(); } |
| // Access to the whole codec list |
| const std::vector<Codec>& codecs() const { return codecs_; } |
| std::vector<Codec>& writable_codecs() { return codecs_; } |
| // Verify consistency of a complete codec list. |
| // Examples: checking that all RTX codecs have APT pointing |
| // to a codec in the list. |
| // The function will CHECK or DCHECK on inconsistencies. It must only be |
| // called once the list is fully assembled. |
| void CheckConsistency(); |
| |
| // Marks the list as complete and moves the codecs out of it. |
| // |
| // This verifies the invariants that only hold for a complete list, such as |
| // every RTX codec referring to a codec that is present, and returns an error |
| // if they are violated. Use this rather than codecs() when handing the |
| // codecs to a caller, so that the verification cannot be forgotten. Unlike |
| // CheckConsistency(), an inconsistent list is reported as an error instead |
| // of being fatal, since a list can become inconsistent as the result of the |
| // codecs an application supplied. |
| // |
| // The CodecList is left empty, whether or not the check succeeded. |
| [[nodiscard]] RTCErrorOr<std::vector<Codec>> Finalize() &&; |
| |
| template <typename Sink> |
| friend void AbslStringify(Sink& sink, const CodecList& list) { |
| absl::Format(&sink, "\n--- Codec list of size %d\n", list.size()); |
| for (Codec codec : list) { |
| absl::Format(&sink, "%v\n", codec); |
| } |
| sink.Append("--- End\n"); |
| } |
| |
| private: |
| // Creates a codec list on trusted data. |
| explicit CodecList(std::span<const Codec> codecs) |
| : codecs_(codecs.begin(), codecs.end()) { |
| CheckConsistency(); |
| } |
| |
| std::vector<Codec> codecs_; |
| }; |
| |
| } // namespace webrtc |
| |
| |
| #endif // MEDIA_BASE_CODEC_LIST_H_ |