| // Copyright 2024 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 "quiche/quic/moqt/moqt_priority.h" | |
| #include <cstdint> | |
| #include <limits> | |
| #include "quiche/web_transport/web_transport.h" | |
| namespace moqt { | |
| namespace { | |
| template <uint64_t NumBits> | |
| constexpr uint64_t Flip(uint64_t number) { | |
| static_assert(NumBits <= 63); | |
| return (1ull << NumBits) - 1 - number; | |
| } | |
| template <uint64_t N> | |
| constexpr uint64_t OnlyLowestNBits(uint64_t value) { | |
| static_assert(N <= 62); | |
| return value & ((1ull << (N + 1)) - 1); | |
| } | |
| } // namespace | |
| // The send order is packed into a signed 64-bit integer as follows: | |
| // 63: always zero to indicate a positive number | |
| // 62: 0 for data streams, 1 for control streams | |
| // 54-61: subscriber priority | |
| // 46-53: publisher priority | |
| // 20-45: group ID | |
| // 0-19: object (for Datagrams) or subgroup (for streams) ID | |
| webtransport::SendOrder SendOrderForStream(MoqtPriority subscriber_priority, | |
| MoqtPriority publisher_priority, | |
| uint64_t group_id, | |
| uint64_t subgroup_id, | |
| MoqtDeliveryOrder delivery_order) { | |
| const int64_t track_bits = (Flip<8>(subscriber_priority) << 54) | | |
| (Flip<8>(publisher_priority) << 46); | |
| group_id = OnlyLowestNBits<26>(group_id); | |
| subgroup_id = OnlyLowestNBits<20>(subgroup_id); | |
| if (delivery_order == MoqtDeliveryOrder::kAscending) { | |
| group_id = Flip<26>(group_id); | |
| } | |
| subgroup_id = Flip<20>(subgroup_id); | |
| return track_bits | (group_id << 20) | subgroup_id; | |
| } | |
| webtransport::SendOrder SendOrderForDatagram(MoqtPriority subscriber_priority, | |
| MoqtPriority publisher_priority, | |
| uint64_t group_id, | |
| uint64_t object_id, | |
| MoqtDeliveryOrder delivery_order) { | |
| return SendOrderForStream(subscriber_priority, publisher_priority, group_id, | |
| object_id, delivery_order); | |
| } | |
| webtransport::SendOrder SendOrderForFetch(MoqtPriority subscriber_priority) { | |
| return (Flip<8>(subscriber_priority) << 54); | |
| } | |
| webtransport::SendOrder UpdateSendOrderForSubscriberPriority( | |
| const webtransport::SendOrder send_order, | |
| MoqtPriority subscriber_priority) { | |
| webtransport::SendOrder new_send_order = OnlyLowestNBits<54>(send_order); | |
| const int64_t sub_bits = Flip<8>(subscriber_priority) << 54; | |
| new_send_order |= sub_bits; | |
| return new_send_order; | |
| } | |
| const webtransport::SendOrder kMoqtControlStreamSendOrder = | |
| std::numeric_limits<webtransport::SendOrder>::max(); | |
| const webtransport::SendOrder kMoqtProbeStreamSendOrder = | |
| std::numeric_limits<webtransport::SendOrder>::min(); | |
| } // namespace moqt |