You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-`pointerId`: The ID of the pointer. There are some predefined values in `ScrcpyPointerId` namespace, but touch screen devices can assign a value for each finger.
36
36
-`pointerX`: The X coordinate of the event.
37
37
-`pointerY`: The Y coordinate of the event.
38
-
-`screenWidth`: The width of the screen. It must match the current video stream resolution to prevent de-synchronization.
39
-
-`screenHeight`: The height of the screen. It must match the current video stream resolution to prevent de-synchronization.
40
-
-`pressure`: The pressure of the event. A floating-point value between 0 and 1.
41
38
-`actionButton`: The button that changed. It's a value of `AndroidMotionEventButton` enum.
42
39
-`buttons`: The state of all the buttons. It's a bit-or combination of `AndroidMotionEventButton` values.
43
40
41
+
### `screenWidth` and `screenHeight`
42
+
43
+
The size of latest video frame.
44
+
45
+
The server will validate these values, and ignore the command if they don't match. This is to prevent invalid `pointerX` and `pointerY` values from being sent to the device, for example when device orientation is changed.
46
+
47
+
When using `AdbScrcpyClient`, it will parse and save the size (if video stream is enabled):
When using one of the [built-in video decoders](../video/index.mdx#decode-and-render-video), the [`sizeChanged` event](../video/tiny-h264.mdx#handle-size-changes) can be used to get the latest `screenWidth` and `screenHeight` values.
| <spanstyle={{marginRight:'2em'}}/> Keyframe Mark | ⛔ | ⛔ |`sendFrameMeta`|`sendFrameMeta`|
43
+
25
44
## Raw mode
26
45
27
-
Since v1.22, if `sendDeviceMeta` and `sendFrameMeta` options are `false`<Versionsince="v2.0">, and `sendCodecMeta` option is also `false`</Version>, the server directly returns the encoded video stream without any encapsulations.
46
+
As the above table shows, since v1.22, if `sendDeviceMeta` and `sendFrameMeta` options are `false`<Versionsince="v2.0">, and `sendCodecMeta` option is also `false`</Version>, all listed fields are not present.
28
47
29
-
In this mode, the video stream only contains codec-specific data. Tango doesn't support parsing the video stream in this mode, but it can be decoded by FFmpeg, or saved directly.
48
+
This is called the raw mode. In this mode, the video socket only contains codec-specific, encoded video data.
30
49
31
-
Otherwise, the video stream contains additional metadata and frame information. The following methods can be used to parse and handle the video stream.
50
+
Without the extra information, it's much harder to process the video stream. Because of that, Tango only has limited support for parsing the video stream in raw mode. Its methods can process the stream without errors, but some fields will be `undefined`, and [built-in video decoders](#decode-and-render-video) can't decode raw mode video stream.
32
51
33
52
## Video stream metadata
34
53
35
-
Scrcpy server first sends some metadata about the video stream:
54
+
If the server [version and options requirements](#format) are met, the server will first send some metadata about the device and the video stream:
-`deviceName`: The device's model name<Versionsince="v1.22">, or `undefined` if `sendDeviceMeta` option is `false`.</Version>.
47
-
-`width` and `height`: Size of the first video frame<Versionsince="v1.22"until='v2.0'>, or `undefined` if `sendDeviceMeta` option is `false`.</Version><Versionsince="v2.0">, or `undefined` if `sendCodecMeta` option is `false`.</Version>.
48
-
-`codec`: The codec returned from server<Versionsince="v2.0">, or the codec inferred from options if `sendCodecMeta` option is `false`.</Version>.
65
+
-`deviceName`: The device's model name.
66
+
-`width`/`height`: Size of the first video frame.
67
+
-`codec`: The codec of the video stream.
49
68
50
-
When device's screen resolution changes (for example, when device rotates, or when a foldable device folds/unfolds), the server restarts video capture and encoding with the new resolution. However, it won't send a new metadata packets with the updated size. The only way to keep track of the video resolution is by parsing the video stream directly. The exact code depends on the video codec.
69
+
### Size changes
70
+
71
+
The metadata will only be sent once. When device screen size changes (for example, when device orientation changes, or a foldable device unfolds), the server will restart the video encoder, but it won't send a new metadata with the new size.
72
+
73
+
To track the video resolution, parsing the video stream is required. [built-in video decoders](#decode-and-render-video) have a [`sizeChanged`](./tiny-h264.mdx#handle-size-changes) event, and [`AdbScrcpyClient`](../start-server.mdx#with-yume-chanadb-scrcpy) has `screenWidth` and `screenHeight` properties.
51
74
52
75
### With `@yume-chan/scrcpy`
53
76
54
-
If you already have a `ReadableStream<Uint8Array>` that reads from the video socket, use the `parseVideoStreamMetadata` method from the corresponding `ScrcpyOptionsX_YY` class to parse the metadata. This method will return the metadata, and a new stream that contains the remaining stream.
77
+
If you already have a `ReadableStream<Uint8Array>` that reads from the video socket, the `parseVideoStreamMetadata` method from the corresponding `ScrcpyOptionsX_YY` class can be used to parse the metadata. This method will return the metadata, and a new stream that contains the remaining stream.
`parseVideoStreamMetadata` also supports raw mode:
93
+
#### `codec`
94
+
95
+
If metadata is not present, or doesn't contain codec information, the `codec` field will <Versionuntil="v2.0">always be `ScrcpyVideoCodecId.H264` because it's the only supported codec</Version><Versionsince="v2.0">be the same as the `videoCodec` option</Version>.
96
+
97
+
#### Raw mode
71
98
72
-
* In `metadata`, only the `codec` field is defined, and is inferred from the option values.
73
-
* The `stream` field is the input `videoSocket` returned as-is.
99
+
If the whole metadata is not present, all fields except `codec` will be `undefined`. The `stream` field returned will be the same object as the parameter.
74
100
75
101
### With `@yume-chan/adb-scrcpy`
76
102
77
-
In `AdbScrcpyClient`, parsing video stream metadata and transforming video packets can be done in a single step. See [the section below](#with-yume-chanadb-scrcpy-1).
103
+
See [`AdbScrcpyClient.prototype.videoStream` property](#with-yume-chanadb-scrcpy-1) below. It uses `parseVideoStreamMetadata` internally to parse the metadata, and it also parses the video stream into packets.
104
+
105
+
The [`codec`](#codec) and [raw mode](#raw-mode-1) behavior mentioned above also apply.
78
106
79
107
## Video packets
80
108
81
-
When not in raw mode, Scrcpy server will encapsulate each encoded video frame with extra information. Tango parses the frames into two types of packets:
109
+
If the server [version and options requirements](#format) are met, the server will encapsulate each encoded video frame with extra information. Tango parses them into two types of packets:
82
110
83
111
```ts
84
112
interfaceScrcpyMediaStreamConfigurationPacket {
@@ -98,29 +126,24 @@ type ScrcpyMediaStreamPacket =
98
126
|ScrcpyMediaStreamDataPacket;
99
127
```
100
128
101
-
The behavior of the packets depends on the `sendFrameMeta` option:
102
-
103
-
| Value |`sendFrameMeta: true`|`sendFrameMeta: false`|
|`ScrcpyMediaStreamConfigurationPacket`| Must be the first packet, but can also appear anywhere | Not exist |
106
-
|`ScrcpyMediaStreamDataPacket.keyframe`|`boolean` indicating if the current packet is a keyframe |`undefined`|
107
-
|`ScrcpyMediaStreamDataPacket.pts`|`bigint` indicating the presentation timestamp |`undefined`|
108
-
109
129
### Configuration packet
110
130
111
-
When the encoder is restarted, a new configuration packet will be generated and sent.
131
+
If present, will always be the first packet. However, when the encoder is restarted, a new configuration packet will be generated and sent.
112
132
113
133
The `data` field contains the codec-specific configuration information:
114
134
115
-
* H.264: Sequence Parameter Set (SPS) and Picture Parameter Set (PPS) in Annex B format.
116
-
* H.265: Video Parameter Set (VPS), Sequence Parameter Set (SPS), and Picture Parameter Set (PPS) in Annex B format.
117
-
* AV1: The first 3 bytes of `AV1CodecConfigurationRecord` (https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox). The remaining configuration OBUs are in the next data packet.
135
+
- H.264: Sequence Parameter Set (SPS) and Picture Parameter Set (PPS) in Annex B format.
136
+
- H.265: Video Parameter Set (VPS), Sequence Parameter Set (SPS), and Picture Parameter Set (PPS) in Annex B format.
137
+
- AV1: The first 3 bytes of `AV1CodecConfigurationRecord` (https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox). The remaining configuration OBUs are in the next data packet.
118
138
119
139
The client should handle this packet and update the decoder accordingly.
120
140
121
141
### Data packet
122
142
123
-
Each data packet contains exactly one encoded frame.
143
+
Each data packet represents exactly one encoded frame, and if [version and options requirements](#format) are met, some extra information:
144
+
145
+
*`keyframe`: `true` if the current packet is a keyframe. Many decoders can decode the video stream without knowing if each frame is a keyframe or not, but some decoders require this information.
146
+
*`pts`: Presentation timestamp in nanoseconds. When rendering the video in real-time, generally you want to present the decoded frames as they arrive to minimize the latency, but this information can be used to remove processing time deviations when [recording](./record.mdx).
124
147
125
148
### With `@yume-chan/scrcpy`
126
149
@@ -156,6 +179,12 @@ videoPacketStream
156
179
157
180
Similar to [`options.clipboard`](../options/index.mdx#watch-device-clipboard-changes), don't `await` the `pipeTo`. The returned `Promise` only resolves when `videoSocket` ends, but waiting here and not handling other streams will block `videoSocket`, causing a deadlock.
158
181
182
+
#### Raw mode
183
+
184
+
If data packet header is not present, the `keyframe` and `pts` fields will be `undefined`.
185
+
186
+
The `data` field contains the data in one `read` call, because there is no packet boundaries, it might contain partial or multiple frames.
187
+
159
188
### With `@yume-chan/adb-scrcpy`
160
189
161
190
When `video` option is not `false`, `AdbScrcpyClient.videoStream` is a `Promise` that resolves to an `AdbScrcpyVideoStream`.
It's very similar to the `videoMetadata` and `videoPacketStream` values in the above section, because `AdbScrcpyClient` calls `parseVideoStreamMetadata` and `createMediaStreamTransformer` internally.
199
+
It uses [`parseVideoStreamMetadata`](#with-yume-chanscrcpy) and [`createMediaStreamTransformer`](#with-yume-chanscrcpy-1) internally, so the return value is a combination of those two methods.
0 commit comments