dfindexeddb 20240519__py3-none-any.whl → 20241105__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,8 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  """Parsers for v8 javascript serialized objects."""
16
+ from __future__ import annotations
17
+
16
18
  from dataclasses import dataclass
17
19
  from datetime import datetime
18
20
  import io
@@ -21,12 +23,13 @@ from typing import Any, BinaryIO, Dict, Optional, Set, Tuple, Union
21
23
 
22
24
  from dfindexeddb import errors
23
25
  from dfindexeddb import utils
26
+ from dfindexeddb.indexeddb import types
24
27
  from dfindexeddb.indexeddb.chromium import definitions
25
28
 
26
29
 
27
30
  @dataclass
28
- class BufferArrayView:
29
- """A parsed Javascript BufferArrayView."""
31
+ class ArrayBufferView:
32
+ """A parsed Javascript ArrayBufferView."""
30
33
  buffer: bytes
31
34
  tag: definitions.V8ArrayBufferViewTag
32
35
  offset: int
@@ -34,48 +37,6 @@ class BufferArrayView:
34
37
  flags: int
35
38
 
36
39
 
37
- class JSArray(list):
38
- """A parsed Javascript array.
39
-
40
- This is a wrapper around a standard Python list to allow assigning arbitrary
41
- properties as is possible in the Javascript equivalent.
42
- """
43
-
44
- def __repr__(self):
45
- array_entries = ", ".join([str(entry) for entry in list(self)])
46
- properties = ", ".join(
47
- f'{key}: {value}' for key, value in self.properties.items())
48
- return f'[{array_entries}, {properties}]'
49
-
50
- @property
51
- def properties(self) -> Dict[str, Any]:
52
- """Returns the object properties."""
53
- return self.__dict__
54
-
55
- def __contains__(self, item):
56
- return item in self.__dict__
57
-
58
- def __getitem__(self, name):
59
- return self.__dict__[name]
60
-
61
-
62
- @dataclass
63
- class Null:
64
- """A parsed Javascript Null."""
65
-
66
-
67
- @dataclass
68
- class RegExp:
69
- """A parsed Javascript RegExp."""
70
- pattern: str
71
- flags: int
72
-
73
-
74
- @dataclass(frozen=True)
75
- class Undefined:
76
- """A parsed Javascript undef."""
77
-
78
-
79
40
  class ValueDeserializer:
80
41
  """A class to deserialize v8 Javascript values/objects.
81
42
 
@@ -194,6 +155,7 @@ class ValueDeserializer:
194
155
  if tag and tag == definitions.V8SerializationTag.ARRAY_BUFFER_VIEW:
195
156
  self._ConsumeTag(tag)
196
157
  result = self._ReadJSArrayBufferView(result)
158
+ self.objects[self._GetNextId()] = result
197
159
  return result
198
160
 
199
161
  def _ReadObjectInternal(self) -> Tuple[definitions.V8SerializationTag, Any]:
@@ -207,9 +169,9 @@ class ValueDeserializer:
207
169
  _ = self.decoder.DecodeUint32Varint()
208
170
  parsed_object = self._ReadObject()
209
171
  elif tag == definitions.V8SerializationTag.UNDEFINED:
210
- parsed_object = Undefined()
172
+ parsed_object = types.Undefined()
211
173
  elif tag == definitions.V8SerializationTag.NULL:
212
- parsed_object = Null()
174
+ parsed_object = types.Null()
213
175
  elif tag == definitions.V8SerializationTag.TRUE:
214
176
  parsed_object = True
215
177
  elif tag == definitions.V8SerializationTag.FALSE:
@@ -369,7 +331,7 @@ class ValueDeserializer:
369
331
 
370
332
  def _ReadJSObjectProperties(
371
333
  self,
372
- js_object: Union[Dict, JSArray],
334
+ js_object: Union[Dict, types.JSArray],
373
335
  end_tag: definitions.V8SerializationTag
374
336
  ) -> int:
375
337
  """Reads key-value properties and sets them to the given js_object.
@@ -385,7 +347,10 @@ class ValueDeserializer:
385
347
  while self._PeekTag() != end_tag:
386
348
  key = self._ReadObject()
387
349
  value = self._ReadObject()
388
- js_object[key] = value
350
+ if isinstance(js_object, dict):
351
+ js_object[key] = value
352
+ else:
353
+ js_object.properties[key] = value
389
354
  num_properties += 1
390
355
  self._ConsumeTag(end_tag)
391
356
  return num_properties
@@ -396,7 +361,7 @@ class ValueDeserializer:
396
361
  self.next_id += 1
397
362
  return next_id
398
363
 
399
- def ReadSparseJSArray(self) -> JSArray:
364
+ def ReadSparseJSArray(self) -> types.JSArray:
400
365
  """Reads a sparse encoded JSArray from the current position.
401
366
 
402
367
  Raises:
@@ -404,13 +369,13 @@ class ValueDeserializer:
404
369
  """
405
370
  next_id = self._GetNextId()
406
371
 
407
- js_array = JSArray()
372
+ js_array = types.JSArray()
408
373
  _, length = self.decoder.DecodeUint32Varint()
409
374
  for _ in range(length):
410
- js_array.append(Undefined())
375
+ js_array.values.append(types.Undefined())
411
376
 
412
377
  num_properties = self._ReadJSObjectProperties(
413
- js_array.__dict__, definitions.V8SerializationTag.END_SPARSE_JS_ARRAY)
378
+ js_array.properties, definitions.V8SerializationTag.END_SPARSE_JS_ARRAY)
414
379
  _, expected_num_properties = self.decoder.DecodeUint32Varint()
415
380
  _, expected_length = self.decoder.DecodeUint32Varint()
416
381
 
@@ -421,7 +386,7 @@ class ValueDeserializer:
421
386
  self.objects[next_id] = js_array
422
387
  return js_array
423
388
 
424
- def ReadDenseJSArray(self) -> JSArray:
389
+ def ReadDenseJSArray(self) -> types.JSArray:
425
390
  """Reads a dense encoded JSArray from the current position.
426
391
 
427
392
  Raises:
@@ -429,7 +394,7 @@ class ValueDeserializer:
429
394
  """
430
395
  next_id = self._GetNextId()
431
396
 
432
- js_array = JSArray()
397
+ js_array = types.JSArray()
433
398
  _, length = self.decoder.DecodeUint32Varint()
434
399
  for _ in range(length):
435
400
  tag = self._PeekTag()
@@ -438,12 +403,12 @@ class ValueDeserializer:
438
403
  continue
439
404
  array_object = self._ReadObject()
440
405
 
441
- if self.version < 11 and isinstance(array_object, Undefined):
406
+ if self.version < 11 and isinstance(array_object, types.Undefined):
442
407
  continue
443
- js_array.append(array_object)
408
+ js_array.values.append(array_object)
444
409
 
445
410
  num_properties = self._ReadJSObjectProperties(
446
- js_array.__dict__, definitions.V8SerializationTag.END_DENSE_JS_ARRAY)
411
+ js_array.properties, definitions.V8SerializationTag.END_DENSE_JS_ARRAY)
447
412
  _, expected_num_properties = self.decoder.DecodeUint32Varint()
448
413
  _, expected_length = self.decoder.DecodeUint32Varint()
449
414
  if num_properties != expected_num_properties:
@@ -496,12 +461,12 @@ class ValueDeserializer:
496
461
  self.objects[next_id] = value
497
462
  return value
498
463
 
499
- def _ReadJSRegExp(self) -> RegExp:
464
+ def _ReadJSRegExp(self) -> types.RegExp:
500
465
  """Reads a Javascript regular expression from the current position."""
501
466
  next_id = self._GetNextId()
502
467
  pattern = self.ReadString()
503
468
  _, flags = self.decoder.DecodeUint32Varint() # TODO: verify flags
504
- regexp = RegExp(pattern=pattern, flags=flags)
469
+ regexp = types.RegExp(pattern=pattern, flags=str(flags))
505
470
  self.objects[next_id] = regexp
506
471
  return regexp
507
472
 
@@ -553,7 +518,10 @@ class ValueDeserializer:
553
518
  return js_set
554
519
 
555
520
  def _ReadJSArrayBuffer(
556
- self, is_shared: bool, is_resizable: bool) -> bytes:
521
+ self,
522
+ is_shared: bool,
523
+ is_resizable: bool
524
+ ) -> bytes:
557
525
  """Reads a Javascript ArrayBuffer from the current position.
558
526
 
559
527
  Args:
@@ -571,6 +539,7 @@ class ValueDeserializer:
571
539
  if is_resizable:
572
540
  _, max_byte_length = self.decoder.DecodeUint32Varint()
573
541
  if byte_length > max_byte_length:
542
+ self.objects[next_id] = array_buffer
574
543
  return array_buffer
575
544
  if byte_length:
576
545
  _, array_buffer = self.decoder.ReadBytes(byte_length)
@@ -589,7 +558,7 @@ class ValueDeserializer:
589
558
  else:
590
559
  flags = 0
591
560
 
592
- return BufferArrayView(
561
+ return ArrayBufferView(
593
562
  buffer=buffer,
594
563
  tag=definitions.V8ArrayBufferViewTag(tag[0]),
595
564
  offset=byte_offset,
@@ -22,9 +22,11 @@ import pathlib
22
22
 
23
23
  from dfindexeddb import utils
24
24
  from dfindexeddb import version
25
+ from dfindexeddb.indexeddb import types
25
26
  from dfindexeddb.indexeddb.chromium import blink
26
27
  from dfindexeddb.indexeddb.chromium import record as chromium_record
27
- from dfindexeddb.indexeddb.chromium import v8
28
+ from dfindexeddb.indexeddb.firefox import gecko
29
+ from dfindexeddb.indexeddb.firefox import record as firefox_record
28
30
  from dfindexeddb.indexeddb.safari import record as safari_record
29
31
 
30
32
 
@@ -39,7 +41,7 @@ class Encoder(json.JSONEncoder):
39
41
  if dataclasses.is_dataclass(o):
40
42
  o_dict = utils.asdict(o)
41
43
  return o_dict
42
- if isinstance(o, bytes):
44
+ if isinstance(o, (bytes, bytearray)):
43
45
  out = []
44
46
  for x in o:
45
47
  if chr(x) not in _VALID_PRINTABLE_CHARACTERS:
@@ -49,13 +51,15 @@ class Encoder(json.JSONEncoder):
49
51
  return ''.join(out)
50
52
  if isinstance(o, datetime):
51
53
  return o.isoformat()
52
- if isinstance(o, v8.Undefined):
53
- return "<undefined>"
54
- if isinstance(o, v8.Null):
55
- return "<null>"
54
+ if isinstance(o, types.Undefined):
55
+ return '<undefined>'
56
+ if isinstance(o, types.JSArray):
57
+ return o.__dict__
58
+ if isinstance(o, types.Null):
59
+ return '<null>'
56
60
  if isinstance(o, set):
57
61
  return list(o)
58
- if isinstance(o, v8.RegExp):
62
+ if isinstance(o, types.RegExp):
59
63
  return str(o)
60
64
  if isinstance(o, enum.Enum):
61
65
  return o.name
@@ -73,13 +77,21 @@ def _Output(structure, output):
73
77
 
74
78
 
75
79
  def BlinkCommand(args):
76
- """The CLI for processing a file as a blink value."""
80
+ """The CLI for processing a file as a blink-encoded value."""
77
81
  with open(args.source, 'rb') as fd:
78
82
  buffer = fd.read()
79
83
  blink_value = blink.V8ScriptValueDecoder.FromBytes(buffer)
80
84
  _Output(blink_value, output=args.output)
81
85
 
82
86
 
87
+ def GeckoCommand(args):
88
+ """The CLI for processing a file as a gecko-encoded value."""
89
+ with open(args.source, 'rb') as fd:
90
+ buffer = fd.read()
91
+ blink_value = gecko.JSStructuredCloneDecoder.FromBytes(buffer)
92
+ _Output(blink_value, output=args.output)
93
+
94
+
83
95
  def DbCommand(args):
84
96
  """The CLI for processing a directory as IndexedDB."""
85
97
  if args.format in ('chrome', 'chromium'):
@@ -88,6 +100,9 @@ def DbCommand(args):
88
100
  use_manifest=args.use_manifest,
89
101
  use_sequence_number=args.use_sequence_number):
90
102
  _Output(db_record, output=args.output)
103
+ elif args.format == 'firefox':
104
+ for db_record in firefox_record.FileReader(args.source).Records():
105
+ _Output(db_record, output=args.output)
91
106
  elif args.format == 'safari':
92
107
  for db_record in safari_record.FileReader(args.source).Records():
93
108
  _Output(db_record, output=args.output)
@@ -115,13 +130,13 @@ def App():
115
130
  subparsers = parser.add_subparsers()
116
131
 
117
132
  parser_blink = subparsers.add_parser(
118
- 'blink', help='Parse a file as a blink value.')
133
+ 'blink', help='Parse a file as a blink-encoded value.')
119
134
  parser_blink.add_argument(
120
- '-s', '--source',
135
+ '-s',
136
+ '--source',
121
137
  required=True,
122
138
  type=pathlib.Path,
123
- help=(
124
- 'The source file.'))
139
+ help='The source file.')
125
140
  parser_blink.add_argument(
126
141
  '-o',
127
142
  '--output',
@@ -130,18 +145,38 @@ def App():
130
145
  'jsonl',
131
146
  'repr'],
132
147
  default='json',
133
- help='Output format. Default is json')
148
+ help='Output format. Default is json.')
134
149
  parser_blink.set_defaults(func=BlinkCommand)
135
150
 
151
+ parser_gecko = subparsers.add_parser(
152
+ 'gecko', help='Parse a file as a gecko-encoded value.')
153
+ parser_gecko.add_argument(
154
+ '-s',
155
+ '--source',
156
+ required=True,
157
+ type=pathlib.Path,
158
+ help='The source file.')
159
+ parser_gecko.add_argument(
160
+ '-o',
161
+ '--output',
162
+ choices=[
163
+ 'json',
164
+ 'jsonl',
165
+ 'repr'],
166
+ default='json',
167
+ help='Output format. Default is json.')
168
+ parser_gecko.set_defaults(func=GeckoCommand)
169
+
136
170
  parser_db = subparsers.add_parser(
137
- 'db', help='Parse a directory as IndexedDB.')
171
+ 'db', help='Parse a directory/file as IndexedDB.')
138
172
  parser_db.add_argument(
139
- '-s', '--source',
173
+ '-s',
174
+ '--source',
140
175
  required=True,
141
176
  type=pathlib.Path,
142
177
  help=(
143
- 'The source IndexedDB folder (for chrome/chromium) '
144
- 'or file (for safari).'))
178
+ 'The source IndexedDB folder (for chrome/chromium) '
179
+ 'or sqlite3 file (for firefox/safari).'))
145
180
  recover_group = parser_db.add_mutually_exclusive_group()
146
181
  recover_group.add_argument(
147
182
  '--use_manifest',
@@ -156,7 +191,11 @@ def App():
156
191
  parser_db.add_argument(
157
192
  '--format',
158
193
  required=True,
159
- choices=['chromium', 'chrome', 'safari'],
194
+ choices=[
195
+ 'chromium',
196
+ 'chrome',
197
+ 'firefox',
198
+ 'safari'],
160
199
  help='The type of IndexedDB to parse.')
161
200
  parser_db.add_argument(
162
201
  '-o',
@@ -166,14 +205,15 @@ def App():
166
205
  'jsonl',
167
206
  'repr'],
168
207
  default='json',
169
- help='Output format. Default is json')
208
+ help='Output format. Default is json.')
170
209
  parser_db.set_defaults(func=DbCommand)
171
210
 
172
211
  parser_ldb = subparsers.add_parser(
173
212
  'ldb',
174
213
  help='Parse a ldb file as IndexedDB.')
175
214
  parser_ldb.add_argument(
176
- '-s', '--source',
215
+ '-s',
216
+ '--source',
177
217
  required=True,
178
218
  type=pathlib.Path,
179
219
  help='The source .ldb file.')
@@ -185,7 +225,7 @@ def App():
185
225
  'jsonl',
186
226
  'repr'],
187
227
  default='json',
188
- help='Output format. Default is json')
228
+ help='Output format. Default is json.')
189
229
  parser_ldb.set_defaults(func=LdbCommand)
190
230
 
191
231
  parser_log = subparsers.add_parser(
@@ -204,7 +244,7 @@ def App():
204
244
  'jsonl',
205
245
  'repr'],
206
246
  default='json',
207
- help='Output format. Default is json')
247
+ help='Output format. Default is json.')
208
248
  parser_log.set_defaults(func=LogCommand)
209
249
 
210
250
  args = parser.parse_args()
@@ -0,0 +1,143 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2024 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # https://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """Definitions for Firefox IndexedDB."""
16
+ from enum import IntEnum
17
+
18
+
19
+ class IndexedDBKeyType(IntEnum):
20
+ """IndexedDB Key Types."""
21
+ TERMINATOR = 0
22
+ FLOAT = 0x10
23
+ DATE = 0x20
24
+ STRING = 0x30
25
+ BINARY = 0x40
26
+ ARRAY = 0x50
27
+
28
+
29
+ MAX_ARRAY_COLLAPSE = 3
30
+ MAX_RECURSION_DEPTH = 64
31
+ MAX_LENGTH = (1 << 30) - 2
32
+ ONE_BYTE_LIMIT = 0x7E
33
+ TWO_BYTE_LIMIT = 0x3FFF + 0x7F
34
+ ONE_BYTE_ADJUST = 1
35
+ TWO_BYTE_ADJUST = -0x7F
36
+ THREE_BYTE_SHIFT = 6
37
+
38
+
39
+ class StructuredDataType(IntEnum):
40
+ """Structured Data Types."""
41
+ FLOAT_MAX = 0xFFF00000
42
+ HEADER = 0xFFF10000
43
+ NULL = 0xFFFF0000
44
+ UNDEFINED = 0xFFFF0001
45
+ BOOLEAN = 0xFFFF0002
46
+ INT32 = 0xFFFF0003
47
+ STRING = 0xFFFF0004
48
+ DATE_OBJECT = 0xFFFF0005
49
+ REGEXP_OBJECT = 0xFFFF0006
50
+ ARRAY_OBJECT = 0xFFFF0007
51
+ OBJECT_OBJECT = 0xFFFF0008
52
+ ARRAY_BUFFER_OBJECT_V2 = 0xFFFF0009
53
+ BOOLEAN_OBJECT = 0xFFFF000A
54
+ STRING_OBJECT = 0xFFFF000B
55
+ NUMBER_OBJECT = 0xFFFF000C
56
+ BACK_REFERENCE_OBJECT = 0xFFFF000D
57
+ DO_NOT_USE_1 = 0xFFFF000E
58
+ DO_NOT_USE_2 = 0xFFFF000F
59
+ TYPED_ARRAY_OBJECT_V2 = 0xFFFF0010
60
+ MAP_OBJECT = 0xFFFF0011
61
+ SET_OBJECT = 0xFFFF0012
62
+ END_OF_KEYS = 0xFFFF0013
63
+ DO_NOT_USE_3 = 0xFFFF0014
64
+ DATA_VIEW_OBJECT_V2 = 0xFFFF0015
65
+ SAVED_FRAME_OBJECT = 0xFFFF0016
66
+ JSPRINCIPALS = 0xFFFF0017
67
+ NULL_JSPRINCIPALS = 0xFFFF0018
68
+ RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_SYSTEM = 0xFFFF0019
69
+ RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_NOT_SYSTEM = 0xFFFF001A
70
+ SHARED_ARRAY_BUFFER_OBJECT = 0xFFFF001B
71
+ SHARED_WASM_MEMORY_OBJECT = 0xFFFF001C
72
+ BIGINT = 0xFFFF001D
73
+ BIGINT_OBJECT = 0xFFFF001E
74
+ ARRAY_BUFFER_OBJECT = 0xFFFF001F
75
+ TYPED_ARRAY_OBJECT = 0xFFFF0020
76
+ DATA_VIEW_OBJECT = 0xFFFF0021
77
+ ERROR_OBJECT = 0xFFFF0022
78
+ RESIZABLE_ARRAY_BUFFER_OBJECT = 0xFFFF0023
79
+ GROWABLE_SHARED_ARRAY_BUFFER_OBJECT = 0xFFFF0024
80
+ TYPED_ARRAY_V1_INT8 = 0xFFFF0100
81
+ TYPED_ARRAY_V1_UINT8 = 0xFFFF0101
82
+ TYPED_ARRAY_V1_INT16 = 0xFFFF0102
83
+ TYPED_ARRAY_V1_UINT16 = 0xFFFF0103
84
+ TYPED_ARRAY_V1_INT32 = 0xFFFF0104
85
+ TYPED_ARRAY_V1_UINT32 = 0xFFFF0105
86
+ TYPED_ARRAY_V1_FLOAT32 = 0xFFFF0106
87
+ TYPED_ARRAY_V1_FLOAT64 = 0xFFFF0107
88
+ TYPED_ARRAY_V1_UINT8_CLAMPED = 0xFFFF0108
89
+ TRANSFER_MAP_HEADER = 0xFFFF0200
90
+ TRANSFER_MAP_PENDING_ENTRY = 0xFFFF0201
91
+ TRANSFER_MAP_ARRAY_BUFFER = 0xFFFF0202
92
+ TRANSFER_MAP_STORED_ARRAY_BUFFER = 0xFFFF0203
93
+ TRANSFER_MAP_END_OF_BUILTIN_TYPES = 0xFFFF0204
94
+
95
+
96
+ class StructuredCloneTags(IntEnum):
97
+ """Structured Clone Tags."""
98
+ BLOB = 0xFFFF8001
99
+ FILE_WITHOUT_LASTMODIFIEDDATE = 0xFFFF8002
100
+ FILELIST = 0xFFFF8003
101
+ MUTABLEFILE = 0xFFFF8004
102
+ FILE = 0xFFFF8005
103
+ WASM_MODULE = 0xFFFF8006
104
+ IMAGEDATA = 0xFFFF8007
105
+ DOMPOINT = 0xFFFF8008
106
+ DOMPOINTREADONLY = 0xFFFF8009
107
+ CRYPTOKEY = 0xFFFF800A
108
+ NULL_PRINCIPAL = 0xFFFF800B
109
+ SYSTEM_PRINCIPAL = 0xFFFF800C
110
+ CONTENT_PRINCIPAL = 0xFFFF800D
111
+ DOMQUAD = 0xFFFF800E
112
+ RTCCERTIFICATE = 0xFFFF800F
113
+ DOMRECT = 0xFFFF8010
114
+ DOMRECTREADONLY = 0xFFFF8011
115
+ EXPANDED_PRINCIPAL = 0xFFFF8012
116
+ DOMMATRIX = 0xFFFF8013
117
+ URLSEARCHPARAMS = 0xFFFF8014
118
+ DOMMATRIXREADONLY = 0xFFFF8015
119
+ DOMEXCEPTION = 0xFFFF80016
120
+ EMPTY_SLOT_9 = 0xFFFF8017
121
+ STRUCTUREDCLONETESTER = 0xFFFF8018
122
+ FILESYSTEMHANDLE = 0xFFFF8019
123
+ FILESYSTEMFILEHANDLE = 0xFFFF801A
124
+ FILESYSTEMDIRECTORYHANDLE = 0xFFFF801B
125
+ IMAGEBITMAP = 0xFFFF801C
126
+ MAP_MESSAGEPORT = 0xFFFF801D
127
+ FORMDATA = 0xFFFF801E
128
+ CANVAS = 0xFFFF801F # This tag is for OffscreenCanvas.
129
+ DIRECTORY = 0xFFFF8020
130
+ INPUTSTREAM = 0xFFFF8021
131
+ STRUCTURED_CLONE_HOLDER = 0xFFFF8022
132
+ BROWSING_CONTEXT = 0xFFFF8023
133
+ CLONED_ERROR_OBJECT = 0xFFFF8024
134
+ READABLESTREAM = 0xFFFF8025
135
+ WRITABLESTREAM = 0xFFFF8026
136
+ TRANSFORMSTREAM = 0xFFFF8027
137
+ VIDEOFRAME = 0xFFFF8028
138
+ ENCODEDVIDEOCHUNK = 0xFFFF8029
139
+ AUDIODATA = 0xFFFF8030
140
+ ENCODEDAUDIOCHUNK = 0xFFFF8031
141
+
142
+
143
+ FRAME_HEADER = b'\xff\x06\x00\x00sNaPpY'