-
Notifications
You must be signed in to change notification settings - Fork 0
/
framediffs.go
128 lines (104 loc) · 3.3 KB
/
framediffs.go
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
package libphonelabgo
import (
"fmt"
phonelab "github.com/shaseley/phonelab-go"
)
// TODO: should rely on charge state
type FrameDiffEmitterGenerator struct{}
func (g *FrameDiffEmitterGenerator) GenerateProcessor(source *phonelab.PipelineSourceInstance,
kwargs map[string]interface{}) phonelab.Processor {
interlace := 0
if val, ok := kwargs["interlace"]; ok {
if interlace, ok = val.(int); !ok {
fmt.Printf("Warning: wrong type for 'interlace' (*T)\n", interlace)
}
}
return &FrameDiffEmitter{
Source: source.Processor,
InterlaceZerosMs: int64(interlace),
}
}
type FrameDiffSample struct {
SFFrameDiff
Inserted bool `json:"inserted"`
TraceTimeAdj float64 `json:"trace_time_adj"`
}
func (sample *FrameDiffSample) MonotonicTimestamp() float64 {
if GlobalConf.UseSysTime {
return float64(sample.Timestamp) / float64(1000.0)
} else {
return sample.TraceTimeAdj
}
}
// State tracker/unpacker
type FrameDiffEmitter struct {
Source phonelab.Processor
InterlaceZerosMs int64
}
func (emitter *FrameDiffEmitter) Process() <-chan interface{} {
outChan := make(chan interface{})
go func() {
inChan := emitter.Source.Process()
// Clock skew between different monotonic clocks.
// Add this to diff timestamps to get trace timestamp.
curOffsetMs := int64(0)
prevToken := int64(-1)
lastTsMs := int64(0)
var prevDiff *SFFrameDiff
for iLog := range inChan {
if ll, ok := iLog.(*phonelab.Logline); ok {
switch t := ll.Payload.(type) {
case *SFFrameDiffLog:
{
// Check token for things that don't look quite right
if prevToken >= 0 && prevToken+1 != t.Token {
fmt.Printf("Warning: Missing tokens. Prev = %v, New = %v\n", prevToken, t.Token)
}
prevToken = t.Token
// Unpack, adjust timestamps, interlace zeros if nec., and send each entry
for _, diff := range t.Diffs {
newDiff := &FrameDiffSample{
SFFrameDiff: *diff,
TraceTimeAdj: adjustTimestampMsToS(diff.Timestamp, curOffsetMs),
Inserted: false,
}
// SurfaceFlinger doesn't swap buffers if no new buffers have been commited,
// which means we don't always get diffs if the screen hasn't changed.
// This adds dummy 0.00 diff entries to help downstream algorithms that expect
// all diffs to be in the stream.
for emitter.InterlaceZerosMs > 0 && lastTsMs > 0 && prevDiff != nil && newDiff.Timestamp-lastTsMs > 2*emitter.InterlaceZerosMs {
newTsMs := lastTsMs + emitter.InterlaceZerosMs
inserted := &FrameDiffSample{
SFFrameDiff: SFFrameDiff{
Timestamp: newTsMs,
PctDiff: float64(0.0),
HasColor: prevDiff.HasColor,
Mode: prevDiff.Mode,
},
TraceTimeAdj: adjustTimestampMsToS(newTsMs, curOffsetMs),
Inserted: true,
}
lastTsMs = newTsMs
outChan <- inserted
}
lastTsMs = newDiff.Timestamp
outChan <- &FrameDiffSample{
SFFrameDiff: *diff,
TraceTimeAdj: adjustTimestampMsToS(diff.Timestamp, curOffsetMs),
Inserted: false,
}
prevDiff = diff
}
}
case *TimeSyncMsg:
{
// Update current time offset
curOffsetMs = t.OffsetNs / nsPerMs
}
}
}
}
close(outChan)
}()
return outChan
}