Low Latency Video Digital Encoding Introduction

Written 2021-08-16

Tags:H264 Video OpenHD NTSC 

Introduction

This is the introduction to a series of posts about digital video encoding, focused on low latency optimization. It's well-known that NTSC's framerate is 29.97Hz(~33.4ms) and fieldrate(half frame to be interleaved) is 59.954(~16.7ms), but the actual latency is much less, just the time required to acquire, filter, modulate, transfer, demodulate, and display. This means that while the whole display may only update 30 times per second, the average age of each pixel value can be almost as low as half that. Assuming no additional delays which are common on LCDs.

But, for many digital streaming systems, frames may buffered several times along the way, which is appropriate for certain tasks, but usually not for low-latency video. I'll discuss where and why that happens, and potential ways around it. Sometimes, I'll use OpenHD as an example.

modifiying mp2307 buck converter boards

Written 2021-08-15

Tags:DCDC power 

I was using some Mini360 DCDC buck converter modules to power raspbery pis when I noticed their output was a little noisy. On the bench with a 5ohm resistive load drawing about an amp, the output ripple was around 950mv, which is quite bad.

MP2307 Buck Converter Mod

The upper two circles(red and yellow) are connected to the input voltage - I added a 10uF capacitor to each, which helped lower the input switching noise. The yellow circles are unpopulated pads, one for input and one for output. I added a 10uF capacitor to the pads in the lower yellow circle, and stacked three more 10uF capacitors around it.

I used 0805 capacitors, but the yellow pads were probably for 0603 parts - this makes them a little tricky to connect. The existing capacitor under the purple was larger than an 0805.

The final result was about 150mV of ripple at 1A - much better but still not great.

Low Latency Video - Cameras

Written 2021-08-15

Tags:H264 Video NTSC 

Today's digital rolling shutter image sensors are usually a 2D array of photodiodes, often with a color filter array directly above them to produce a Bayer RGB pattern. To produce a frame, a small controller selects a row and column to select a photodiode, then connects that to a PGA(Programmable Gain Amplifier), then to an ADC(Analog to digital converter) whose output is sent over a data bus to the ISP(image signal processor, may be in another chip). Some image sensors contain an integrated ISP, but this is not common in the Raspberry Pi cameras.

The signal available at the ADC is a product of the PGA gain and the exposure time for each photodiode. If we halve the exposure time and double the gain, the picture should be about as bright, but with more noise visible, since the PGA amplifies noise too.

Internally, the camera's scanrate/framerate will create a limitation for exposure time - a 30FPS camera cannot expose each pixel for more than ~33ms, but we can usually also reduce this exposure time and keep the same framerate - this is our first latency limitation - the average signal age for a 33ms exposure time camera is ~16ms. If enough light is available, we can reduce this time and increase gain until the image is just barely not quite too noisy.

The data link to the ISP creates another limitation too - if the data link is fully saturated(always transmitting, 100% duty cycle) in a given image sensor configuration, we cannot stream pixels faster than the framerate - as soon as the last subpixel in the sensor is read, the sensor has to start streaming out the first pixel of the next frame. This creates rolling shutter artifacts due to the time delay in reading the pixels at different locations in the sensor. This isn't a direct cause of latency since each pixel is still only at most exposureTime old, but can be reduced by shortening the number of pixels sent or using a faster or wider datalink.

Alarm.com VVTK8112 WiFi Puck Camera Serial Console

Written 2021-07-25

Tags:vivotek alarm.com 

My house came with a partially working security system, including a WiFi camera with 256MB RAM, 128MB SPI Flash,

Alarm.com puck camera

There's a Vivotek ARM9 chip with a serial port inside at 38400 baud, on J6, which is on the lower-left of the photo below and I'm not sure but looks like a 4 pin JST mini connector. Pin4 is ground, Pin3 is TX from the device. I did not try to talk to it, but RX should be pins 1 or 2.

Alarm.com puck camera

Here's what it said to me:

U-Boot 2009.06-2.0.6-svn186232 (May 05 2016 - 13:24:05)

=== U-Boot DDR Reserved Area ===
  !! Please do not write any data to these locations. !!
  TEXT section  : 0x00002000 -> 0x0001ee38
  BSS  section  : 0x0001ee38 -> 0x00020afc
  MALLOC Area   : 0x00020afc -> 0x00320afc
  STACK         : 0x00320b7c -> 0x0036bb88
  GMAC Desc/Buf : 0x0036bba0 -> 0x00377da0

=== DRAM Configuration ===
  Bank #0      : 0x00000000 256 MB

=== GPIO Configuration ===

=== NAND Configuration ===
SPIFLASH: Got idcode ff c8 21 7f 7f
SF: Detected PSU1GS20BN with page size 2048, total 128 MB
  Flash Type   : SPI NAND Flash Chip.
Bad block table found at page 65472, version 0x01
Bad block table found at page 65408, version 0x01
  Chip Size    : 128 MiB

=== Boot Configuration ===
  Boot Storage : Serial NAND Flash
  Finding the environment variables in boot storage...
*** Warning - bad CRC or NAND, using default environment


=== Model Name ===
  Model Name : VVTK8112

=== Loader Info ===
  Loader Version# : 0x15050701 (This value is stored at 0x41001000)
Boot from = SN
Hit hotkey: b, d, n, u
Flash status = 255
NAND Reading : #
NAND Reading : ##############ECC corrected = 1
###
 2186856 bytes read: OK
   Image Name:   linux-3.10.49
   Created:      2017-04-13   8:19:40 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2186792 Bytes =  2.1 MB
   Load Address: 00408000
   Entry Point:  00408000
   Verifying Checksum ... OK
NAND Reading : #
NAND Reading : #
 6389 bytes read: OK
   Image Name:   linux-3.10.49
   Created:      2015-11-09   6:26:37 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    6325 Bytes =  6.2 kB
   Load Address: 00408000
   Entry Point:  00408000
   Verifying Checksum ... OK
NAND Reading : #
NAND Reading : ####################################ECC corrected = 1
########################################ECC corrected = 1
####################
 12525632 bytes read: OK
   Image Name:   Rootfs
   Created:      2017-04-13   8:24:35 UTC
   Image Type:   ARM Linux Filesystem Image (uncompressed)
   Data Size:    12525568 Bytes = 11.9 MB
   Load Address: 02ffffc0
   Entry Point:  03000000
   Verifying Checksum ... OK
## Booting Linux kernel at 0x00a00040 ...
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 3.10.49 (hayes.hsu@rd1-3) (gcc version 4.9.1 (Buildroot 2014.08) ) #13 PREEMPT Thu Apr 13 16:19:34 CST 2017
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: VATICS Pesaro SoC (Flattened Device Tree), model: Pesaro SoC
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 34544
Kernel command line: root=/dev/ram0 ro initrd=0x3000000,32M ramdisk_size=32000 mem=136M console=2,38400 user_debug=31 phy_mode=mii
PID hash table entries: 1024 (order: 0, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 136MB = 136MB total
Memory: 99068k/99068k available, 40196k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    vmalloc : 0xc9000000 - 0xff000000   ( 864 MB)
    lowmem  : 0xc0000000 - 0xc8800000   ( 136 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .text : 0xc0008000 - 0xc0563a44   (5487 kB)
      .init : 0xc0564000 - 0xc05859c4   ( 135 kB)
      .data : 0xc0586000 - 0xc05bf310   ( 229 kB)
       .bss : 0xc05bf310 - 0xc05e1338   ( 137 kB)
Preemptible hierarchical RCU implementation.
NR_IRQS:16 nr_irqs:16 16
SYSC counter at clock 12000000
TMRC at APB bus clock 100000000
vpl_sys_timer_init virq 16
sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 4294967286ms
Console: colour dummy device 80x30
Calibrating delay loop... 298.59 BogoMIPS (lpj=1492992)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0xc0406620 - 0xc040665c
devtmpfs: initialized
pinctrl core: initialized pinctrl subsystem
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
lm device registered, virq: 33!
bio: create slab  at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Advanced Linux Sound Architecture Driver Initialized.
Switching to clocksource sysc_freerun_counter
FS-Cache: Loaded
NET: Registered protocol family 2
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP: reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
Trying to unpack rootfs image as initramfs...
rootfs image is not initramfs (junk in compressed archive); looks like an initrd
Freeing initrd memory: 32768K (c3000000 - c5000000)
squashfs: version 4.0 (2009/01/31) Phillip Lougher
fuse init (API version 7.22)
msgmni has been set to 257
alg: No test for stdrng (krng)
io scheduler noop registered
io scheduler deadline registered (default)
io scheduler cfq registered
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
ab800000.serial: ttyS0 at MMIO 0xab800004 (irq = 18) is a 16550A
ac000000.serial: ttyS1 at MMIO 0xac000004 (irq = 19) is a 16550A
ac800000.serial: ttyS2 at MMIO 0xac800004 (irq = 20) is a 16550A
console [ttyS2] enabled
ad000000.serial: ttyS3 at MMIO 0xad000004 (irq = 21) is a 16550A
brd: module loaded
GPIO Device Driver version 1.0.0.1
dws->irq  17, get 17
dws->max_freq 100000000
dw_spi_mmio a0800000.spi: master is unqueued, this is deprecated
 id: c8 21
NAND device: Manufacturer ID: 0xc8, Chip ID: 0x21 (Unknown Mira PSU1GS20 1G 3.3V SPI), 128MiB, page size: 2048, OOB size: 64
Bad block table found at page 65472, version 0x01
Bad block table found at page 65408, version 0x01
5 ofpart partitions found on MTD device spi0.0
Creating 5 MTD partitions on "spi0.0":
0x000000000000-0x000008000000 : "Boot"
0x000002d00000-0x000004d00000 : "Rootfs"
0x000004d00000-0x000005500000 : "Flashfs-1"
0x000005500000-0x000007e00000 : "Flashfs-2"
0x000007e00000-0x000008000000 : "NFDI"
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky 
GMAC: PHY mode is mii
stmmac - user ID: 0x10, Synopsys ID: 0x40
 DMA HW capability register supported
 RX Checksum Offload Engine supported
 TX Checksum insertion supported
clk rate 200000000
	eth0 - (dev. name: 90000000.dw_eqos - id: -1, IRQ #0
	IO base addr: 0xc910c000)
libphy: dweqos_mdio: probed
PPP generic driver version 2.4.2
PPP BSD Compression module registered
PPP Deflate Compression module registered
PPP MPPE Compression module registered
NET: Registered protocol family 24
usbcore: registered new interface driver usb-storage
rtc-s35390a 0-0030: error resetting chip
rtc-s35390a: probe of 0-0030 failed with error -5
i2c /dev entries driver
vpl_wdt ad800000.vpl_wdt: VPL Watchdog Timer Hardware Rev 0x01020000
vpl_wdt ad800000.vpl_wdt: Driver Version 1.0.0.0: initial timeout 60 sec, nowayout=1
Synopsys Designware Multimedia Card Interface Driver
dwmmc_pesaro 92000000.dwmmc0: dev-id: 0
dwmmc_pesaro 92000000.dwmmc0: Using internal DMA controller.
dwmmc_pesaro 92000000.dwmmc0: Version ID is 270a
dwmmc_pesaro 92000000.dwmmc0: DW MMC controller at irq 25, 32 bit host data width, 16 deep fifo
dwmmc_pesaro 92000000.dwmmc0: 1 slots initialized
ip_tables: (C) 2000-2006 Netfilter Core Team
TCP: cubic registered
NET: Registered protocol family 10
ip6_tables: (C) 2000-2006 Netfilter Core Team
NET: Registered protocol family 17
8021q: 802.1Q VLAN Support v1.8
Key type dns_resolver registered
/home/vivotek/lsp/rossini/kernel_platform/kernel/pesaro_kernel_3.10_r50403-r50221/drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
ALSA device list:
  No soundcards found.
RAMDISK: squashfs filesystem found at block 0
RAMDISK: Loading 12232KiB [1 disk] into ram disk... |/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|/-\|done.
VFS: Mounted root (squashfs filesystem) readonly on device 1:0.
Freeing unused kernel memory: 132K (c0564000 - c0585000)
init started: BusyBox v1.22.1 (2017-04-13 16:20:08 CST)
UBI: attaching mtd2 to ubi0
UBI: scanning is finished
UBI: attached mtd2 (name "Flashfs-1", size 8 MiB) to ubi0
UBI: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
UBI: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
UBI: VID header offset: 2048 (aligned 2048), data offset: 4096
UBI: good PEBs: 64, bad PEBs: 0, corrupted PEBs: 0
UBI: user volume: 1, internal volumes: 1, max. volumes count: 128
UBI: max/mean erase counter: 245/145, WL threshold: 4096, image sequence number: 134069212
UBI: available PEBs: 0, total reserved PEBs: 64, PEBs reserved for bad PEB handling: 20
UBI: background thread "ubi_bgt0d" started, PID 72
UBI device number 0, total 64 LEUBI: attaching mtd3 to ubi1
Bs (8126464 bytes, 7.8 MiB), available 0 LEBs (0 bytes), LEB size 126976 bytes (124.0 KiB)
UBI: scanning is finished
UBI: attached mtd3 (name "Flashfs-2", size 41 MiB) to ubi1
UBI: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
UBI: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
UBI: VID header offset: 2048 (aligned 2048), data offset: 4096
UBI: good PEBs: 328, bad PEBs: 0, corrupted PEBs: 0
UBI: user volume: 1, internal volumes: 1, max. volumes count: 128
UBI: max/mean erase counter: 50/29, WL threshold: 4096, image sequence number: 1431253369
UBI: available PEBs: 0, total reserved PEBs: 328, PEBs reserved for bad PEB handling: 20
UBI: background thread "ubi_bgt1d" started, PID 76
UBI device number 1, total 328 LEBs (41648128 bytes, 39.7 MiB), UBIFS: background thread "ubifs_bgt0_0" started, PID 79
available 0 LEBs (0 bytes), LEB size 126976 bytes (124.0 KiB)
UBIFS: recovery needed
UBIFS: recovery completed
UBIFS: mounted UBI device 0, volume 0, name "flashfs"
UBIFS: LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes
UBIFS: FS size: 3809280 bytes (3 MiB, 30 LEBs), journal size 1015809 bytes (0 MiB, 6 LEBs)
UBIFS: reserved for root: 179921 bytes (175 KiB)
UBIFS: media format: w4/r0 (latest is w4/r0), UUID 14966A3A-210E-4496-8B7F-B4CD7ECAE98B, small LPT model
UBIFS: background thread "ubifs_bgt1_0" started, PID 82
UBIFS: recovery needed
UBIFS: recovery completed
UBIFS: mounted UBI device 1, volume 0, name "flashfs2"
UBIFS: LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes
UBIFS: FS size: 37330944 bytes (35 MiB, 294 LEBs), journal size 1904640 bytes (1 MiB, 15 LEBs)
UBIFS: reserved for root: 1763232 bytes (1721 KiB)
UBIFS: media format: w4/r0 (latest is w4/r0), UUID 1682BFE5-2F31-4E62-86CA-8864A163DC97, small LPT model
/etc exist
Build fifo for media
kernel.msgmnb = 65536
vm.dirty_ratio = 1
vm.dirty_background_ratio = 1
vm.min_free_kbytes = 4096
vm.vfs_cache_pressure = 163
vm.panic_on_oom = 2
kernel.panic = 1
.sys.module.cifs.parameters.enable_oplocks = 0
check apply_patch_before
run-parts -a start /etc/rcS.d
"dpc" is not exist!
"dpc" read fail! 
Read DPC table fail!
VPL_EDMC: initialized (driver 6.1.0.5 HW 14.6.0.2) Oct 12 2015 20:12:28
DRAM 0 base address = 0x08800000, size = 0x07800000
Install VPL_DMAC device driver version 1.0.0.0 on VPL_DMAC hardware version 2.1.0.0 complete !!
Install VMA_JEBE device driver version 1.0.0.1 on VMA_JEBE hardware version 1.4.0.23 complete !!
Install VMA_H4CDE device driver version 2.0.0.7 on VMA_H4EE hardware version 16.1.0.43 complete !!
Install VMA_ISPE device driver version 7.0.0.0 on VMA_ISPE hardware version 4.7.0.3 complete !!
Install VPL_VIC device driver version 2.0.8.12 on VPL_VIC hardware version 7.0.0.12 complete !!
[IMX225]: Device 0 insmod success.
IMX225_Init Done!
Install autoexposure driver version 7.0.0.1 complete !!
Install autowhitebalance driver version 4.0.0.0 complete !!
ICR Device Driver version 1.0.0.0
soc-audio soc-audio.0: ASoC: machine pesaro_evm should use snd_soc_register_card()
soc-audio soc-audio.0:  dwc-hifi <-> vatics-pcm mapping ok
soc-audio soc-audio.0:  hdmi-hifi <-> vatics-pcm mapping ok
Starting led: .
Starting restore: .
Starting configer: .
Starting shm_allocate: .
Starting vadpshmalloc: .
Starting swatchdog: .
Starting synctime: Thu Jan  1 00:00:00 UTC 2015
.
Starting chronos: .
Starting ectun: .
Starting eventmgr: Starting eventmgr with support for EcTun
.
Starting radvdump: .
.
Starting /etc/rcS.d/S14network: eth0: device MAC address 00:02:d1:47:d3:24
dweqos 90000000.dw_eqos eth0: dweqos_init_phy: trying to attach to dweqos_mdio-ffff:01
dweqos 90000000.dw_eqos eth0: dweqos_init_phy: attached to PHY (UID 0x2430c54) Link = 1
dweqos 90000000.dw_eqos eth0: PHY: ICPlus IP101A/G
.
dwc_otg: version 3.0.0.3(3.10a 21-DEC-2012)
dwc_otg lm0: USB PHY CTRL value: 0x821c06e4
dwc_otg lm0:  Host only
Core Release: 3.10a
Setting default values for core params
Setting core params with module parameters
Using Buffer DMA mode
Periodic Transfer Interrupt(PTI) Enhancement - disabled
Multiprocessor Interrupt(MPI) Enhancement - disabled
OTG VER PARAM: 0, OTG VER FLAG: 0
dwc_otg lm0: DWC OTG Controller
dwc_otg lm0: new USB bus registered, assigned bus number 1
dwc_otg lm0: irq 33, io mem 0x00000000
Init: Power Port (0)
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
Waiting for releasing memory, free memory: 93636
Indeed it is in host mode hprt0 = 00021501
usb 1-1: new high-speed USB device number 2 using dwc_otg
Indeed it is in host mode hprt0 = 00001101
Waiting for releasing memory, free memory: 93800
REALTEK_RTL8192EU
RTL871X: module init start
RTL871X: rtl8192eu v4.3.8_12406.20140929
RTL871X: build time: Jun  6 2016 16:53:44
RTL871X: 
usb_endpoint_descriptor(0):
RTL871X: bLength=7
RTL871X: bDescriptorType=5
RTL871X: bEndpointAddress=84
RTL871X: wMaxPacketSize=512
RTL871X: bInterval=0
RTL871X: RT_usb_endpoint_is_bulk_in = 4
RTL871X: 
usb_endpoint_descriptor(1):
RTL871X: bLength=7
RTL871X: bDescriptorType=5
RTL871X: bEndpointAddress=5
RTL871X: wMaxPacketSize=512
RTL871X: bInterval=0
RTL871X: RT_usb_endpoint_is_bulk_out = 5
RTL871X: 
usb_endpoint_descriptor(2):
RTL871X: bLength=7
RTL871X: bDescriptorType=5
RTL871X: bEndpointAddress=6
RTL871X: wMaxPacketSize=512
RTL871X: bInterval=0
RTL871X: RT_usb_endpoint_is_bulk_out = 6
RTL871X: 
usb_endpoint_descriptor(3):
RTL871X: bLength=7
RTL871X: bDescriptorType=5
RTL871X: bEndpointAddress=87
RTL871X: wMaxPacketSize=64
RTL871X: bInterval=3
RTL871X: RT_usb_endpoint_is_int_in = 7, Interval = 3
RTL871X: 
usb_endpoint_descriptor(4):
RTL871X: bLength=7
RTL871X: bDescriptorType=5
RTL871X: bEndpointAddress=8
RTL871X: wMaxPacketSize=512
RTL871X: bInterval=0
RTL871X: RT_usb_endpoint_is_bulk_out = 8
RTL871X: nr_endpoint=5, in_num=2, out_num=3

RTL871X: USB_SPEED_HIGH
RTL871X: CHIP TYPE: RTL8192E
RTL871X: register rtw_netdev_ops to netdev_ops
RTL871X: ReadChipVersion192e 0xF0 = 0xc441135 
RTL871X: Chip Version Info: CHIP_8192E_Normal_Chip_SMIC_B_CUT_2T2R_RomVer(0)
RTL871X: RF_Type is 2!!
RTL871X: _ConfigChipOutEP_8192E OutEpQueueSel(0x07), OutEpNumber(3) 
RTL871X: ====> ReadAdapterInfo8192EU
RTL871X: Boot from EFUSE, Autoload OK !
RTL871X: EEPROM ID=0x8129
RTL871X: VID = 0x0BDA, PID = 0x818B
RTL871X: Customer ID: 0x00, SubCustomer ID: 0xCD
RTL871X: hal_ReadMACAddress_8192EU MAC Address from EFUSE = 5c:f3:70:31:7e:a6
RTL871X: Hal_ReadPowerSavingMode8192E...bHWPwrPindetect(0)-bHWPowerdown(0) ,bSupportRemoteWakeup(1)
RTL871X: ### PS params=>  power_mgnt(0),usbss_enable(0) ###
RTL871X: EEPROMRegulatory = 0x1 TxPwrCalibrateRate=0x0
RTL871X: Board Type: Dongle or WIFI only Module 
RTL871X: mlmepriv.ChannelPlan = 0x22
RTL871X: CrystalCap: 0x23
RTL871X: ThermalMeter = 0x1a
RTL871X: SWAS: bHwAntDiv = 0, TRxAntDivType = ff
RTL871X: pHalData->PAType_2G is 0x0, pHalData->ExternalPA_2G = 0
RTL871X: pHalData->LNAType_2G is 0x0, pHalData->ExternalLNA_2G = 0
RTL871X: ReadAdapterInfo8192EU <====
RTL871X: Hal_ChannelPlanToRegulation ChannelPlan:0x22,Regulation(2_4G/5G):0x00,0x03
RTL871X: init_channel_set ChannelPlan ID 22 Chan num:11  
RTL871X: rtw_alloc_macid(eth%d) if1, hwaddr:ff:ff:ff:ff:ff:ff macid:1
RTL871X: rtw_macaddr_cfg MAC Address  = 00:02:d1:47:d3:24
RTL871X: bDriverStopped:1, bSurpriseRemoved:0, bup:0, hw_init_completed:0
RTL871X: rtw_ndev_init(wlan0)
RTL871X: _rtw_drv_register_netdev, MAC Address (if1) = 00:02:d1:47:d3:24
usbcore: registered new interface driver rtl8192eu
RTL871X: module init ret=0
RTL871X: +871x_drv - drv_open, bup=0
RTL871X: ==>_InitPowerOn_8192EU 
RTL871X: SetHwReg8192E: bMacPwrCtrlOn=1
RTL871X:  ===> FirmwareDownload88E() fw source from Header.
RTL871X: FirmwareDownload8192E fw:NIC, size: 31818
RTL871X: FirmwareDownload8192E: fw_ver=19 fw_subver=0 sig=0x92e1
RTL871X: polling_fwdl_chksum: Checksum report OK! (1, 0ms), REG_MCUFWDL:0x00070305
RTL871X: =====> _8051Reset8192E(): 8051 reset success .
RTL871X: _FWFreeToGo8192E: Polling FW ready OK! (82, 30ms), REG_MCUFWDL:0x000706c6
RTL871X: FWDL success. write_fw:1, 100ms
RTL871X: ===> phy_BB8192E_Config_ParaFile() EEPROMRegulatory 1
RTL871X: PHY_BBConfig8192E ==> CrystalCap:0x23 
RTL871X: Auto InitLLTTable8192E success 
RTL871X: pDM_Odm TxPowerTrackControl = 1
RTL871X: phy_SpurCalibration_8192E =>AFE_PHASE_SEL 
RTL871X: ===FixSpur NOT Pass!
RTL871X: wlan0 MAC Address from REG_MACID = 00:02:d1:47:d3:24
RTL871X: rtl8192eu_hal_init in 1870ms
RTL871X: wlan0Port-0  set opmode = 2
RTL871X: MAC Address = 00:02:d1:47:d3:24
RTL871X: -871x_drv - drv_open, bup=1
IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready
RTL871X: rtw_ioctl_standard_wext_private:...
RTL871X: _rtw_ioctl_wext_private: cmd=mp_priv_ver
RTL871X: _rtw_ioctl_wext_private: parameters=
RTL871X: mp_get MP_GETVER 
RTL871X: rtw_ioctl_standard_wext_private:...
RTL871X: _rtw_ioctl_wext_private: cmd=efuse_get
RTL871X: _rtw_ioctl_wext_private: parameters=rmap,b8,1
RTL871X: efuse get EFUSE_GET 
RTL871X: rtw_pm_set_ips IPS_NONE
RTL871X: rtw_mp_efuse_get: in=rmap,b8,1
RTL871X: rtw_mp_efuse_get: addr=b8
RTL871X: rtw_mp_efuse_get: cnts=1
RTL871X: rtw_pm_set_ips IPS_NONE
RTL871X: (2)871x_drv - drv_close, bup=1, hw_init_completed=1
RTL871X: indicate disassoc
RTL871X: +rtl8192e_set_FwJoinBssReport_cmd(wlan0): iface_type=0 mstatus(0)
RTL871X: HW_VAR_BASIC_RATE: 0x15f -> 0x15f -> 0x15f
RTL871X: -871x_drv - drv_close, bup=1
Wait for eth0 ready!(0)
Wait for eth0 ready!(1)
Wait for eth0 ready!(2)
[S14network] Waiting for config_wireless_mode
.
.
.
.
.
RTL871X: +871x_drv - drv_open, bup=1
RTL871X: -871x_drv - drv_open, bup=1
IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready
RTL871X: [rtw_wx_set_pmkid] IW_PMKSA_FLUSH!
RTL871X: set_mode = IW_MODE_INFRA
RTL871X: wlan0Port-0  set opmode = 2
RTL871X: set bssid:00:00:00:00:00:00
RTL871X: [rtw_wx_set_pmkid] IW_PMKSA_FLUSH!
.
.
.
.
.
[S14network] config_wireless_mode finished
udhcpc (v1.22.1) started
Sending discover...
Sending discover...
Sending discover...
network_ipaddress=0.0.0.0
network_subnet=
network_router=
network_dns1=
network_dns2=
network_wins1=
network_wins2=
No lease, forking to background
.
 * Starting ip filter with iptables... 
iptables/ip6tables disabled

[ ok ]
Starting syslogd: .
Anubis architecture
router=
UPnP CP disabled
Starting adec: config file parse OK!!
Initial FIFO succeeded, fd = 3
src/audioout_alsPLL Unlock....
a.c:79:open audio-out device (0x14e7980)
snd_pcm_hw_params set period size 320
[Georgie] boundary: 1073741824
dwGainPercentage = 0, dwGain = 411
.
Starting aenc: .
Starting venc: .
Starting mod: .
sensor initial 
Starting rtsps: [IMX225]: Open device 0 done 
run as daemon mode
.
Starting serverpush: .
Starting httpd: .
.
https_status=1
Starting stunnel: [VIC] : open success!!
sensor no support WDR   742 root      3192 S    /usr/sbin/stunnel /etc/conf.d/stunnel.conf
.
Starting recorder: .
Starting inetd: .
Starting upnpdd: .
Starting iod: .
Cannot resolve 'deviceapi.alarm.com:443' - delaying DNS lookup
Starting uartd: .
Starting vpnwatch: .
Starting ddnsc: change 
 ddns server name :  127.0.0.1
DDNS run as daemon coz specific service providers
Starting snapshotd: Total stream num: 4, default stream ID: -1
Entering daemon mode...
.
Starting vid: .
Starting ptzmanager:
Driver not found
.
Starting alarmaudioupstream: .
.
test network status...
killall: imgbufmgr: no process killed
RTL871X: rtw_wx_get_rts, rts_thresh=2347
RTL871X: rtw_wx_get_frag, frag_len=2346
RTL871X: rtw_wx_get_rts, rts_thresh=2347
RTL871X: rtw_wx_get_frag, frag_len=2346
RTL871X: rtw_wx_get_rts, rts_thresh=2347
RTL871X: rtw_wx_get_frag, frag_len=2346
RTL871X: rtw_wx_get_rts, rts_thresh=2347
RTL871X: rtw_wx_get_frag, frag_len=2346
RTL871X: rtw_wx_get_rts, rts_thresh=2347
RTL871X: rtw_wx_get_frag, frag_len=2346
ls: /mnt/CF/link2: No such file or directory
Send FIFO  Cmd :stop
Send FIFO  Cmd :stop
Send FIFO  Cmd :stop
Send FIFO  Cmd :stop
Send FIFO  Cmd /stop
config file parse OK!!
Sector[0] = 4341760
Sector[1] = 4341760
Sector[2] = 4341760
end
config file parse OK!!
Sector[0] = 1310720
end
send bootup command to eventmgr
Send FIFO  Cmd )start
Send FIFO  Cmd .trigger
Enable sysinfo.cgi
Starting ovpn: .
Not support AutoFocus nor BackFoucs, leave!
Starting guard: .
Starting ddnsc_watchdog: .
Starting eventmgr_watchdog: .
Starting removeToken: .
Starting upload_vadp: .
Starting vadprscmgr: .
Starting vadplic: .
check apply_patch_after

Network-Camera login: 

Installing Magisk on Raspberry Pi 4 OmniROM Android 11

Written 2021-07-15

Tags:OmniROM Android Magisk 

Magisk is a great tool for rooted devices, but the installation process for Raspberry Pi 4 running Android is a little different than most.

Magisk Installation Process

Magisk is normally installed by installing the Magisk App APK, then using it to patch a boot.img. See the upstream instructions here. Notably, this won't work with any files you'll see on a Raspberry Pi 4 /boot filesystem.

It was puzzling because the Magisk app shows "Ramdisk: Yes" on the Raspberry Pi 4, but /boot does not have one, and the usual sources for patching images don't have one either.

Android Boot Process

See this overview and this list of Android image files, but the important part is that Android usually boots by having the bootloader loads the kernel and ramdisk from a single boot.img, then jumps to the kernel.

Raspbery Pi 4 Boot Mechanism

From this stack overflow post, we can see that the Raspberry Pi 4 boots the GPU first, loads start.elf into the GPU, which reads a config.txt from the SD (or other sources) filesystem, and follows the instructions in config.txt.

From the OmniROM for RPi4 boot image, we can see it is only slightly different from the usual config.txt, in that a few files are renamed, here are their lines:

kernel=Image
initramfs ramdisk.img followkernel

TLDR: The solution

Since Magisk is expecting a boot.img, we need to create one in the format Android usually uses, patch it using the Magisk App, extract the patched recovery.img out of the boot.img, then install it.

Here are the tools we'll need:

Here are the steps, a little more verbose, starting from scratch, and assuming we're installing from a Linux computer.
  1. Insert the microSD card into the Linux workstation
  2. If the first microSD card partition does not mount, mount it manually. Mine was under /media/rsaxvc/rpi4/boot
  3. Combine the Kernel Image file with the ramdisk using mkbootimg. Here was my command to create image.bin ./mkbootimg --kernel /media/rsaxvc/rpi4/boot/Image --ramdisk /media/rsaxvc/rpi4/boot/ramdisk.img --output image.bin
  4. We will need to transfer the image.bin somewhere the Magisk app can read it like the downloads folder, but I just pushed it to a webserver and downloaded it later
  5. Unmount all filesystems on the microSD card, eject it, insert into Raspberry Pi 4
  6. Boot the Raspberry Pi 4. When it comes up, launch the Magisk App
  7. Patch as usual but stop when it tells you to copy the patched image back to the PC. I will note that the file picker on OmniROM seemed to crash loading .img files - I think I had to right-click the boot.img icon to toggle selection
  8. Once the patching is complete and succeeds, shutdown the Raspberry Pi 4
  9. Move the microSD card back to the workstation and mount at least the first(/boot) partition and the last partition which contains the Downloads folder
  10. Backup the original ramdisk.img from the microSD card /boot partition
  11. In the Downloads folder, the Magisk app will have written magisk_patched_[random_strings].img. Copy it to a local temporary directory, this may need to be done as root due to permissions
  12. fix the ownership/permissions if needed
  13. Unpack contents into a folder with with ./unpackbootimg -i magisk_patched-[random_strings].img
  14. Inside the folder will be a file magisk_patched-[random-strings].img-ramdisk.gz - move to the microSD card's /boot/ramdisk.img
  15. Unmount all microSD card partitions eject the card, and insert into Raspberry Pi 4
  16. Boot up the device, Magisk should now be fully installed - this did take a minute or two for it to start the first time

Older