-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathuser_timestamp_h265_parser.go
More file actions
94 lines (81 loc) · 2.42 KB
/
user_timestamp_h265_parser.go
File metadata and controls
94 lines (81 loc) · 2.42 KB
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
package lksdk
import (
"bytes"
"encoding/binary"
"fmt"
)
// parseH265SEIUserTimestamp parses H265 prefix SEI NAL units (type 39) carrying
// user_data_unregistered messages and returns a timestamp (microseconds) when detected.
//
// Expected payload format (after the 2-byte NAL header):
//
// payloadType = 5 (user_data_unregistered)
// payloadSize = 24
// UUID = 16 bytes (3fa85f64-5717-4562-b3fc-2c963f66afa6)
// timestamp_us = 8 bytes, big-endian
// trailing = 0x80 (stop bits + padding)
func parseH265SEIUserTimestamp(nalData []byte) (int64, bool) {
if len(nalData) < 3 {
logger.Infow("H265 SEI user_data_unregistered: nal too short", "nal_len", len(nalData))
return 0, false
}
// Skip 2-byte NAL header.
payload := nalData[2:]
i := 0
// Parse payloadType (can be extended with 0xFF bytes).
payloadType := 0
for i < len(payload) && payload[i] == 0xFF {
payloadType += 255
i++
}
if i >= len(payload) {
logger.Infow("H265 SEI user_data_unregistered: payloadType truncated", "payload_len", len(payload))
return 0, false
}
payloadType += int(payload[i])
i++
// We only care about user_data_unregistered (type 5).
if payloadType != 5 {
return 0, false
}
// Parse payloadSize (can be extended with 0xFF bytes).
payloadSize := 0
for i < len(payload) && payload[i] == 0xFF {
payloadSize += 255
i++
}
if i >= len(payload) {
logger.Infow("H265 SEI user_data_unregistered: payloadSize truncated", "payload_len", len(payload))
return 0, false
}
payloadSize += int(payload[i])
i++
if payloadSize < 24 || len(payload) < i+payloadSize {
// Not enough data for UUID (16) + timestamp (8).
logger.Infow(
"H265 SEI user_data_unregistered: insufficient data for UUID + timestamp",
"payloadSize", payloadSize,
"payload_len", len(payload),
"offset", i,
)
return 0, false
}
userData := payload[i : i+payloadSize]
uuidBytes := userData[:16]
tsBytes := userData[16:24]
// Validate the UUID matches the exact user timestamp UUID we expect.
if !bytes.Equal(uuidBytes, userTimestampSEIUUID[:]) {
return 0, false
}
timestampUS := binary.BigEndian.Uint64(tsBytes)
// Format UUID as 8-4-4-4-12 hex segments (for debug logs).
uuid := fmt.Sprintf("%x-%x-%x-%x-%x",
uuidBytes[0:4],
uuidBytes[4:6],
uuidBytes[6:8],
uuidBytes[8:10],
uuidBytes[10:16],
)
logger.Debugw("H265 SEI user_data_unregistered parsed", "uuid", uuid, "timestamp_us", timestampUS)
return int64(timestampUS), true
}