parent
8cbe34a810
commit
8068fee939
1 changed files with 100 additions and 0 deletions
@ -0,0 +1,100 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
import argparse |
||||||
|
import bisect |
||||||
|
import select |
||||||
|
import sys |
||||||
|
import termios |
||||||
|
import time |
||||||
|
import tty |
||||||
|
from collections import defaultdict |
||||||
|
|
||||||
|
import cereal.messaging as messaging |
||||||
|
from tools.lib.framereader import FrameReader |
||||||
|
from tools.lib.logreader import LogReader |
||||||
|
|
||||||
|
IGNORE = ['initData', 'sentinel'] |
||||||
|
|
||||||
|
|
||||||
|
def input_ready(): |
||||||
|
return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []) |
||||||
|
|
||||||
|
|
||||||
|
def replay(route, segment): |
||||||
|
route = route.replace('|', '/') |
||||||
|
|
||||||
|
lr = LogReader(f"cd:/{route}/{segment}/rlog.bz2") |
||||||
|
fr = FrameReader(f"cd:/{route}/{segment}/fcamera.hevc", readahead=True) |
||||||
|
|
||||||
|
# Build mapping from frameId to segmentId from encodeIdx, type == fullHEVC |
||||||
|
msgs = [m for m in lr if m.which() not in IGNORE] |
||||||
|
msgs = sorted(msgs, key=lambda m: m.logMonoTime) |
||||||
|
times = [m.logMonoTime for m in msgs] |
||||||
|
frame_idx = {m.encodeIdx.frameId: m.encodeIdx.segmentId for m in msgs if m.which() == 'encodeIdx' and m.encodeIdx.type == 'fullHEVC'} |
||||||
|
|
||||||
|
socks = {} |
||||||
|
lag = 0 |
||||||
|
i = 0 |
||||||
|
max_i = len(msgs) - 2 |
||||||
|
|
||||||
|
while True: |
||||||
|
msg = msgs[i].as_builder() |
||||||
|
next_msg = msgs[i + 1] |
||||||
|
|
||||||
|
start_time = time.time() |
||||||
|
w = msg.which() |
||||||
|
|
||||||
|
if w == 'frame': |
||||||
|
try: |
||||||
|
img = fr.get(frame_idx[msg.frame.frameId], pix_fmt="rgb24") |
||||||
|
img = img[0][:, :, ::-1] # Convert RGB to BGR, which is what the camera outputs |
||||||
|
msg.frame.image = img.flatten().tobytes() |
||||||
|
except KeyError: |
||||||
|
pass |
||||||
|
|
||||||
|
if w not in socks: |
||||||
|
socks[w] = messaging.pub_sock(w) |
||||||
|
socks[w].send(msg.to_bytes()) |
||||||
|
|
||||||
|
lag += (next_msg.logMonoTime - msg.logMonoTime) / 1e9 |
||||||
|
lag -= time.time() - start_time |
||||||
|
|
||||||
|
dt = max(lag, 0) |
||||||
|
lag -= dt |
||||||
|
time.sleep(dt) |
||||||
|
|
||||||
|
if lag < -1 and i % 100 == 0: |
||||||
|
print(f"{-lag} s behind") |
||||||
|
|
||||||
|
if input_ready(): |
||||||
|
key = sys.stdin.read(1) |
||||||
|
|
||||||
|
# Handle pause |
||||||
|
if key == " ": |
||||||
|
while True: |
||||||
|
if input_ready() and sys.stdin.read(1) == " ": |
||||||
|
break |
||||||
|
time.sleep(0.01) |
||||||
|
|
||||||
|
# Handle seek |
||||||
|
dt = defaultdict(int, s=10, S=-10)[key] |
||||||
|
new_time = msgs[i].logMonoTime + dt * 1e9 |
||||||
|
i = bisect.bisect_left(times, new_time) |
||||||
|
|
||||||
|
i = (i + 1) % max_i |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument("route") |
||||||
|
parser.add_argument("segment", type=int) |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
orig_settings = termios.tcgetattr(sys.stdin) |
||||||
|
tty.setcbreak(sys.stdin) |
||||||
|
|
||||||
|
try: |
||||||
|
replay(args.route, args.segment) |
||||||
|
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings) |
||||||
|
except: |
||||||
|
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings) |
||||||
|
raise |
Loading…
Reference in new issue