File size: 7,250 Bytes
44bafb2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# All credits to https://github.com/LuanRT/googlevideo

from pytubefix.sabr.common import FormatId
from pytubefix.sabr.proto import BinaryWriter, BinaryReader
from pytubefix.sabr.video_streaming.time_range import TimeRange


def create_base_buffered_range():
    return {
        "formatId": None,
        "startTimeMs": 0,
        "durationMs": 0,
        "startSegmentIndex": 0,
        "endSegmentIndex": 0,
        "timeRange": None,
        "field9": None,
        "field11": None,
        "field12": None
    }

class Kob_Pa:

    def __init__(self):
        self.videoId = ""
        self.lmt = 0

    @staticmethod
    def encode(message, writer=None):
        writer = writer or BinaryWriter()
        if message.get("videoId"):
            writer.uint32(10).string(message["videoId"])
        if message.get("lmt", 0) != 0:
            writer.uint32(16).uint64(message["lmt"])
        return writer

    @staticmethod
    def decode(input_data, length=None):
        reader = input_data if isinstance(input_data, BinaryReader) else BinaryReader(input_data)
        end = reader.len if length is None else reader.pos + length

        message = Kob_Pa()
        while reader.pos < end:
            tag = reader.uint32()
            field_num = tag >> 3

            if field_num == 1 and tag == 10:
                message.videoId = reader.string()
                continue
            elif field_num == 2 and tag == 16:
                message.lmt = long_to_number(reader.uint64())
            elif (tag & 7) == 4 or tag == 0:
                break
            else:
                reader.skip(tag & 7)
        return message


class Kob:

    def __init__(self):
        self.EW = []

    @staticmethod
    def encode(message, writer=None):
        writer = writer or BinaryWriter()
        for v in message.get("EW", []):
            Kob_Pa.encode(v, writer.uint32(10).fork()).join()
        return writer

    @staticmethod
    def decode(input_data, length=None):
        reader = input_data if isinstance(input_data, BinaryReader) else BinaryReader(input_data)
        end = reader.len if length is None else reader.pos + length

        message = Kob()
        while reader.pos < end:
            tag = reader.uint32()
            field_num = tag >> 3

            if field_num == 1 and tag == 10:
                message.EW.append(Kob_Pa.decode(reader, reader.uint32()))
                continue

            elif (tag & 7) == 4 or tag == 0:
                break
            else:
                reader.skip(tag & 7)
        return message


class YPa:

    def __init__(self):
        self.field1 = 0
        self.field2 = 0
        self.field3 = 0

    @staticmethod
    def encode(message, writer=None):
        writer = writer or BinaryWriter()
        if message.get("field1", 0) != 0:
            writer.uint32(8).int32(message["field1"])
        if message.get("field2", 0) != 0:
            writer.uint32(16).int32(message["field2"])
        if message.get("field3", 0) != 0:
            writer.uint32(24).int32(message["field3"])
        return writer

    @staticmethod
    def decode(input_data, length=None):
        reader = input_data if isinstance(input_data, BinaryReader) else BinaryReader(input_data)
        end = reader.len if length is None else reader.pos + length

        message = YPa()
        while reader.pos < end:
            tag = reader.uint32()
            field_num = tag >> 3

            if field_num == 1 and tag == 8:
                message.field1 = reader.int32()
                continue
            elif field_num == 2 and tag == 16:
                message.field2 = reader.int32()
                continue
            elif field_num == 3 and tag == 24:
                message.field3 = reader.int32()
                continue

            elif (tag & 7) == 4 or tag == 0:
                break
            else:
                reader.skip(tag & 7)
        return message


class BufferedRange:
    @staticmethod
    def encode(message, writer=None):
        writer = writer or BinaryWriter()
        if message.get("formatId") is not None:
            FormatId.encode(message["formatId"], writer.uint32(10).fork()).join()
        if message.get("startTimeMs", 0) != 0:
            writer.uint32(16).int64(message["startTimeMs"])
        if message.get("durationMs", 0) != 0:
            writer.uint32(24).int64(message["durationMs"])
        if message.get("startSegmentIndex", 0) != 0:
            writer.uint32(32).int32(message["startSegmentIndex"])
        if message.get("endSegmentIndex", 0) != 0:
            writer.uint32(40).int32(message["endSegmentIndex"])
        if message.get("timeRange") is not None:
            TimeRange.encode(message["timeRange"], writer.uint32(50).fork()).join()
        if message.get("field9") is not None:
            Kob.encode(message["field9"], writer.uint32(74).fork()).join()
        if message.get("field11") is not None:
            YPa.encode(message["field11"], writer.uint32(90).fork()).join()
        if message.get("field12") is not None:
            YPa.encode(message["field12"], writer.uint32(98).fork()).join()
        return writer

    @staticmethod
    def decode(input_data, length=None):
        reader = input_data if isinstance(input_data, BinaryReader) else BinaryReader(input_data)
        end = reader.len if length is None else reader.pos + length

        message = create_base_buffered_range()
        while reader.pos < end:
            tag = reader.uint32()
            field_num = tag >> 3

            if field_num == 1 and tag == 10:
                message["formatId"] = FormatId.decode(reader, reader.uint32())
                continue
            elif field_num == 2 and tag == 16:
                message["startTimeMs"] = long_to_number(reader.int64())
                continue
            elif field_num == 3 and tag == 24:
                message["durationMs"] = long_to_number(reader.int64())
                continue
            elif field_num == 4 and tag == 32:
                message["startSegmentIndex"] = reader.int32()
                continue
            elif field_num == 5 and tag == 40:
                message["endSegmentIndex"] = reader.int32()
                continue
            elif field_num == 6 and tag == 50:
                message["timeRange"] = TimeRange.decode(reader, reader.uint32())
                continue
            elif field_num == 9 and tag == 74:
                message["field9"] = Kob.decode(reader, reader.uint32())
                continue
            elif field_num == 11 and tag == 90:
                message["field11"] = YPa.decode(reader, reader.uint32())
                continue
            elif field_num == 12 and tag == 98:
                message["field12"] = YPa.decode(reader, reader.uint32())
                continue
            elif (tag & 7) == 4 or tag == 0:
                break
            else:
                reader.skip(tag & 7)
        return message

def long_to_number(int64_value):
    value = int(str(int64_value))
    if value > (2 ** 53 - 1):
        raise OverflowError("Value is larger than 9007199254740991")
    if value < -(2 ** 53 - 1):
        raise OverflowError("Value is smaller than -9007199254740991")
    return value