Fix error in MoQT Relative Location encoding.

Not in production

PiperOrigin-RevId: 606996381
diff --git a/quiche/quic/moqt/moqt_framer.cc b/quiche/quic/moqt/moqt_framer.cc
index 2c46476..61caf1e 100644
--- a/quiche/quic/moqt/moqt_framer.cc
+++ b/quiche/quic/moqt/moqt_framer.cc
@@ -91,7 +91,7 @@
     }
     return writer.WriteVarInt62(loc->absolute_value);
   }
-  if (loc->relative_value < 0) {
+  if (loc->relative_value <= 0) {
     if (!writer.WriteVarInt62(static_cast<uint64_t>(
             MoqtSubscribeLocationMode::kRelativePrevious))) {
       return false;
@@ -103,7 +103,7 @@
           static_cast<uint64_t>(MoqtSubscribeLocationMode::kRelativeNext))) {
     return false;
   }
-  return writer.WriteVarInt62(static_cast<uint64_t>(loc->relative_value));
+  return writer.WriteVarInt62(static_cast<uint64_t>(loc->relative_value - 1));
 }
 
 }  // namespace
diff --git a/quiche/quic/moqt/moqt_parser.cc b/quiche/quic/moqt/moqt_parser.cc
index b8754f2..ac72183 100644
--- a/quiche/quic/moqt/moqt_parser.cc
+++ b/quiche/quic/moqt/moqt_parser.cc
@@ -600,7 +600,7 @@
       loc = MoqtSubscribeLocation(false, -1 * static_cast<int64_t>(ui64));
       break;
     case MoqtSubscribeLocationMode::kRelativeNext:
-      loc = MoqtSubscribeLocation(false, static_cast<int64_t>(ui64));
+      loc = MoqtSubscribeLocation(false, static_cast<int64_t>(ui64) + 1);
       break;
     default:
       ParseError("Unknown location mode");
diff --git a/quiche/quic/moqt/moqt_parser_test.cc b/quiche/quic/moqt/moqt_parser_test.cc
index c0f1e9b..278c39f 100644
--- a/quiche/quic/moqt/moqt_parser_test.cc
+++ b/quiche/quic/moqt/moqt_parser_test.cc
@@ -10,6 +10,7 @@
 #include <memory>
 #include <optional>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "absl/strings/string_view.h"
@@ -860,4 +861,31 @@
   EXPECT_FALSE(visitor_.parsing_error_.has_value());
 }
 
+TEST_F(MoqtMessageSpecificTest, RelativeLocation) {
+  MoqtParser parser(kRawQuic, visitor_);
+  char subscribe[] = {
+      0x03, 0x01, 0x02,              // id and alias
+      0x03, 0x66, 0x6f, 0x6f,        // track_namespace = "foo"
+      0x04, 0x61, 0x62, 0x63, 0x64,  // track_name = "abcd"
+      0x02, 0x00,                    // start_group = 0 (relative previous)
+      0x03, 0x00,                    // start_object = 1 (relative next)
+      0x00,                          // end_group = none
+      0x00,                          // end_object = none
+#ifdef MOQT_AUTH_INFO
+      0x01,                          // 1 parameter
+      0x02, 0x03, 0x62, 0x61, 0x72,  // authorization_info = "bar"
+#endif
+  };
+  parser.ProcessData(absl::string_view(subscribe, sizeof(subscribe)), false);
+  EXPECT_EQ(visitor_.messages_received_, 1);
+  MoqtSubscribe message = std::get<MoqtSubscribe>(*visitor_.last_message_);
+  EXPECT_FALSE(visitor_.parsing_error_.has_value());
+  ASSERT_TRUE(message.start_group.has_value());
+  ASSERT_FALSE(message.start_group->absolute);
+  EXPECT_EQ(message.start_group->relative_value, 0);
+  ASSERT_TRUE(message.start_object.has_value());
+  ASSERT_FALSE(message.start_object->absolute);
+  EXPECT_EQ(message.start_object->relative_value, 1);
+}
+
 }  // namespace moqt::test