Skip to content

Commit

Permalink
m1n1/avd: Add initial AVD driver prototype/tracer
Browse files Browse the repository at this point in the history
Not much to see here, most of the juice is over at:

    https://github.com/eiln/avd.git

The kernel driver (m1n1.fw.avd) only really pipes the instruction stream
into the respective hardware FIFOs and then hushes the interrupt lines.
Most of the work (bitstream syntax parsing and instruction generation)
is done in the avid repo above.

I'm hoping to keep this userland-kernel separation in the very imminent
actual driver.

experiments/avd.py: Decode on the command line. Read file for usage.
experiments/avd_e.py: Decode via emulated instruction stream.
experiments/avd_f.py: Decode via Cortex-M3 firmware (for debugging).
hv/trace_avd.py: Tracer. Read file for usage.
m1n1/fw/avd/__init__.py: Driver base class (power, tunables, etc).
m1n1/fw/avd/decoder.py: Codec-specific decode logic + mini media player.

Signed-off-by: Eileen Yoon <[email protected]>
  • Loading branch information
eiln authored and marcan committed Jan 11, 2024
1 parent 90eef72 commit 16a6b41
Show file tree
Hide file tree
Showing 6 changed files with 1,013 additions and 0 deletions.
86 changes: 86 additions & 0 deletions proxyclient/experiments/avd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
import sys, pathlib, argparse
sys.path.append(str(pathlib.Path(__file__).resolve().parents[1]))
sys.path.append("/home/eileen/asahi/avd") # git clone https://github.com/eiln/avd.git
# Decode with our own generated instruction stream

from m1n1.setup import *
from m1n1.utils import *
from m1n1.fw.avd import *
from tools.common import ffprobe

if __name__ == "__main__":
parser = argparse.ArgumentParser()
#
# Usage:
# ffmpeg -i input.mp4 -c:v copy (or reencode libx264) input.264
# python3 experiments/avd.py -i input.264 -a
#
# - Supports .264, .265, and .ivf formats.
# - Regarding the codec, it's whatever codec features are supported.
# Check avid for details.
# - Also ensure to change the sys.path.append above to the avid repo
# as it does not install system-wide.
#
parser.add_argument('-i', '--input', type=str, required=True, help="path to input bitstream")
parser.add_argument('-n', '--num', type=int, default=1, help="frame count")
parser.add_argument('-a', '--all', action='store_true', help="run all frames")
parser.add_argument('-x', '--stfu', action='store_true')
parser.add_argument('-p', '--poll', action='store_true', help="poll iommu space")
parser.add_argument('--save-raw', type=str, default="", help="file name to save raw yuv")
parser.add_argument('--save-images', type=str, default="", help="dirname to save images")
args = parser.parse_args()
mode = ffprobe(args.input)

if (mode == "h264"):
from avid.h264.decoder import AVDH264Decoder
dec = AVDH264Decoder()
elif (mode == "h265"):
from avid.h265.decoder import AVDH265Decoder
dec = AVDH265Decoder()
elif (mode == "vp09"):
from avid.vp9.decoder import AVDVP9Decoder
dec = AVDVP9Decoder()
else:
raise RuntimeError("unsupported codec")
if (args.stfu):
dec.stfu = True
dec.hal.stfu = True
nal_stop = 0 if args.all else 1
units = dec.setup(args.input, nal_stop=nal_stop, num=args.num)

avd = AVDDevice(u)
if (mode == "h264"):
avd.decoder = AVDH264Dec(avd)
elif (mode == "h265"):
avd.decoder = AVDH265Dec(avd)
elif (mode == "vp09"):
avd.decoder = AVDVP9Dec(avd)
else:
raise RuntimeError("unsupported codec")
avd.decoder.winname = args.input
if (args.stfu):
avd.stfu = True
avd.boot()

rawvideo = b''
num = len(units) if args.all else min(args.num, len(units))
for i,unit in enumerate(units[:num]):
print(unit)
inst = dec.decode(unit)
if (i == 0):
avd.ioalloc_at(0x0, dec.allocator_top(), stream=0, val=0)
if (args.poll):
avd.iomon.add(0x0, dec.allocator_top())
frame = avd.decoder.decode(dec.ctx, unit, inst)
if (frame != None):
if (args.save_raw):
rawvideo += frame.y_data + frame.uv_data
if (args.save_images):
os.makedirs(f"data/out/{args.save_images}", exist_ok=True)
path = os.path.join(f"data/out/{args.save_images}", "out%03d.png" % (avd.decoder.count))
cv2.imwrite(path, frame.img)
if (args.save_raw):
path = os.path.join(f"data/out/{args.save_raw}")
open(path, "wb").write(rawvideo)
79 changes: 79 additions & 0 deletions proxyclient/experiments/avd_e.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
import sys, pathlib, argparse, os
sys.path.append(str(pathlib.Path(__file__).resolve().parents[1]))
sys.path.append("/home/eileen/asahi/avd") # git clone https://github.com/eiln/avd.git
# Decode via firmware-emulated AVD instruction stream

from m1n1.setup import *
from m1n1.utils import *
from m1n1.fw.avd import *

from avd_emu import AVDEmulator
from tools.common import ffprobe

if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', type=str, required=True, help="input bitstream")
parser.add_argument('-d', '--dir', type=str, required=True, help="path to trace dir")
parser.add_argument('-f', '--firmware', type=str, default="data/fw.bin", help="path to fw")
parser.add_argument('-n', '--num', type=int, default=1, help="count")
parser.add_argument('-a', '--all', action='store_true', help="run all")
parser.add_argument('-x', '--stfu', action='store_true')
parser.add_argument('-p', '--poll', action='store_true', help="poll iommu space")
parser.add_argument('--save-raw', action='store_true', help="save raw yuv")
args = parser.parse_args()
mode = ffprobe(args.input)

emu = AVDEmulator(args.firmware, stfu=True)
emu.start()
paths = os.listdir(os.path.join(args.dir))
paths = sorted([os.path.join(args.dir, path) for path in paths if "frame" in path])
assert(len(paths))
num = len(paths) if args.all else args.num
num = min(len(paths), num)

if (mode == "h264"):
from avid.h264.decoder import AVDH264Decoder
dec = AVDH264Decoder()
elif (mode == "h265"):
from avid.h265.decoder import AVDH265Decoder
dec = AVDH265Decoder()
elif (mode == "vp09"):
from avid.vp9.decoder import AVDVP9Decoder
dec = AVDVP9Decoder()
else:
raise RuntimeError("unsupported codec")
if (args.stfu):
dec.stfu = True
dec.hal.stfu = True
units = dec.setup(args.input)

avd = AVDDevice(u)
if (mode == "h264"):
avd.decoder = AVDH264Dec(avd)
elif (mode == "h265"):
avd.decoder = AVDH265Dec(avd)
elif (mode == "vp09"):
avd.decoder = AVDVP9Dec(avd)
else:
raise RuntimeError("unsupported codec")
avd.decoder.winname = args.input
if (args.stfu):
avd.stfu = True
avd.boot()
avd.ioalloc_at(0x0, 0xf000000, stream=0)
if (args.poll):
avd.iomon.add(0x0, 0xf000000)

for i,unit in enumerate(units[:num]):
print(unit)
inst = dec.decode(unit)
path = paths[i]
print(path)
inst = emu.avd_cm3_cmd_decode(path)
avd.decoder.decode(dec.ctx, unit, inst)
if (args.save_raw):
y_data = avd.ioread(dec.ctx.y_addr, dec.ctx.luma_size, stream=0)
uv_data = avd.ioread(dec.ctx.uv_addr, dec.ctx.chroma_size, stream=0)
open("data/raw-emu/%03d.bin" % (i), "wb").write(y_data + uv_data)
63 changes: 63 additions & 0 deletions proxyclient/experiments/avd_fw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
import sys, pathlib, argparse
sys.path.append(str(pathlib.Path(__file__).resolve().parents[1]))
sys.path.append("/home/eileen/asahi/avd") # git clone https://github.com/eiln/avd.git
# Decode via AVD Cortex-M3 firmware

from m1n1.setup import *
from m1n1.utils import *
from m1n1.fw.avd import *
import cv2

from avd_emu import AVDEmulator
from avid.h264.decoder import AVDH264Decoder
from avid.vp9.decoder import AVDVP9Decoder
from avid.utils import *
from tools.common import *

if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-f','--firmware', type=str, default="data/fw.bin", help="path to CM3 firmware")
parser.add_argument('-i','--input', type=str, required=True, help="path to CM3 firmware")
parser.add_argument('-d','--dir', type=str, required=True, help="frame_params trace dir")
parser.add_argument('-p', '--poll', action='store_true', help="poll iommu space")
args = parser.parse_args()

paths = os.listdir(os.path.join(args.dir))
paths = sorted([os.path.join(args.dir, path) for path in paths if "frame" in path])
assert(len(paths))

avd = AVDDevice(u)
avd.decoder = AVDVP9Dec(avd)
avd.boot()
avd.mcpu_decode_init(args.firmware)
avd.poll()

avd.ioalloc_at(0x0, 0xff0000, stream=0)
if (args.poll):
avd.iomon.add(0x0, 0xff0000)
avd.ioalloc_at(0x0, 0xb84000, stream=1)
avd.iomon.poll()
emu = AVDEmulator(args.firmware, stfu=True)
emu.start()

dec = AVDVP9Decoder()
dec.stfu = True
dec.hal.stfu = True
units = dec.setup(args.input, num=4, do_probs=True)
for n,unit in enumerate(units):
inst = dec.decode(unit)
avd.decoder.set_payload(dec.ctx, units[n])
avd.decoder.avd.iowrite(dec.ctx.probs_addr, unit.get_probs(), stream=0)
avd.iomon.poll()
cmd = emu.set_params(paths[n])
xxde(cmd)
avd.iowrite(0x0, emu.dart1_space, stream=1)
avd.iomon.poll()
avd.avd_wbuf(emu.get_cmd_addr(n), cmd)
avd.avd_w32(0x1098054, emu.get_cmd_addr(n))
avd.poll()
avd.iomon.poll()
img = avd.decoder.get_nv12_disp_frame(dec.ctx)
cv2.imshow(avd.decoder.winname, img); cv2.waitKey(1)
Loading

0 comments on commit 16a6b41

Please sign in to comment.