Update: I picked up another card with a similar chipset (saa7130). The card was detected by default but did not work well. Setting it manually to the reference design made it work straight away.
02.2021 uptate: For some reason a version of mplayer that got installed as an update stopped recognizing the -tv option. The option syntax has apparently changed, I updated the post to reflect that
Recently I picked up an ABEST ABDVR 4 channel PCI video capture card. The card has no EEPROM, and becuase of that the saa7134 driver is unable to autoidentify it. In this post I'll show you how to configure v4l2 to get an image out of this card and how to use libav filters to make a vectorscope and a waveform monitor using mpv and bash.
It's an saa7134 based contraption with 4 digitizers connected to a PCI-to-PCI bridge. This setup allows for 4 independent capture processes running at the same time. The card has 4 BNC jacks. The label in black marker was added by me because there isn't any model name on the PCB.
lspci -v output shows the bridge IC and the 4 digitizers:
05:09.0 PCI bridge: Pericom Semiconductor PI7C8140A PCI-to-PCI Bridge (prog-if 00 [Normal decode]) Flags: bus master, 66MHz, medium devsel, latency 66 Bus: primary=05, secondary=06, subordinate=06, sec-latency=66 Memory behind bridge: fc800000-fcafffff Capabilities: [80] Power Management version 2 Capabilities: [90] CompactPCI hot-swap > Kernel modules: shpchp 06:0c.0 Multimedia controller: Philips Semiconductors SAA7134/SAA7135HL Video Broadcast Decoder (rev 01) Subsystem: Philips Semiconductors SAA713x-based TV tuner card Flags: bus master, medium devsel, latency 66, IRQ 18 Memory at fca00000 (32-bit, non-prefetchable) [size=1K] Capabilities: [40] Power Management version 1 Kernel driver in use: saa7134 Kernel modules: saa7134 06:0d.0 Multimedia controller: Philips Semiconductors SAA7134/SAA7135HL Video Broadcast Decoder (rev 01) Subsystem: Philips Semiconductors SAA713x-based TV tuner card Flags: bus master, medium devsel, latency 66, IRQ 21 Memory at fca00400 (32-bit, non-prefetchable) [size=1K] Capabilities: [40] Power Management version 1 Kernel driver in use: saa7134 Kernel modules: saa7134 06:0e.0 Multimedia controller: Philips Semiconductors SAA7134/SAA7135HL Video Broadcast Decoder (rev 01) Subsystem: Philips Semiconductors SAA713x-based TV tuner card Flags: bus master, medium devsel, latency 66, IRQ 22 Memory at fca00800 (32-bit, non-prefetchable) [size=1K] Capabilities: [40] Power Management version 1 Kernel driver in use: saa7134 Kernel modules: saa7134 06:0f.0 Multimedia controller: Philips Semiconductors SAA7134/SAA7135HL Video Broadcast Decoder (rev 01) Subsystem: Philips Semiconductors SAA713x-based TV tuner card Flags: bus master, medium devsel, latency 66, IRQ 16 Memory at fca00c00 (32-bit, non-prefetchable) [size=1K] Capabilities: [40] Power Management version 1 Kernel driver in use: saa7134 Kernel modules: saa7134
The card shows up as 4 video devices in /dev/, in my case video0 through video3
Since this card has no EEPROM, the saa7134 module cannot identify it and falls back to the GENERIC/UNKNOWN model. This model definition does not have inputs 1 and 2 enabled (each of the saa7134 ICs has 3 selectable video inputs) In case of my card, the video signal is coming in to input 1 instead of 0. To be able to capture video, we need to tell the saa7134 driver to treat it as a different card - one that has all 3 inputs enabled in the driver, and then we can select input 1.
If the driver fails to recognize the card, it prints a list of known IDs and card names to the kernel buffer. One of the listed cards, Philips Tiger - S Reference design, sounded like it would work so I set the driver to use that (id 109), instead of trying to autodetect.
Put this in /etc/modprobe.d/saa7134.conf:
options saa7134 card=109,109,109,109
There are 4 values, each one for one digitizer. You have to reboot or reload the saa7134 module to apply these changes
As I mentioned, each of the digitizers receives the video signal on input 1. In order to view the video, you need to specify the input by adding --tv-input=1 to mplayer/mpv's parameters.
mpv tv:// --tv-driver=v4l2 --tv-device=/dev/video1 --tv-input=1 --tv-norm=0
You can pass other parameters as well, one of the more useful ones is --tv-norm= that allows you to select between NTSC, and a multitude of PAL or SECAM standards. There are many other parameters as well, but they are used for tv tuner cards.
I wrote a script that allows me to run two mpv processes in paralell to be able to see two streams at once.
#!/bin/bash clean(){ exit 0; } trap clean SIGINT # set norm to 4 for PAL mpv tv:// --tv-driver=v4l2 --tv-device=/dev/video0 --tv-input=1 --tv-norm=0 \ --title="video0" & mpv tv:// --tv-driver=v4l2 --tv-device=/dev/video1 --tv-input=1 --tv-norm=0 \ --title="video1" & wait
Two video streams being received by the card. The left camera's lens can be seen on the right image in the corner, which is the video from another camera
02.2021: Updated the script syntax for the new mpv/mplayer version
libav has a lot of various filters which can be used in most applications, including mpv and ffmpeg. Here's a script that runs mpv on one of the framegrabber inputs and creates a virtual waveform monitor and vectorscope using the libav filtergraph
mpv tv:// --tv-driver=v4l2 --tv-device=/dev/video1 --tv-input=1 --tv-norm=0 \ --vf=lavfi='[split=3 [a][b][c], [b]waveform[wfm], [c]vectorscope=color4, scale=736x736[color], [a][wfm] vstack [left], [left][color] hstack ]'
The filtergraph is a very powerful tool. Here is a different example with all three displays on top of each other
mpv tv:// --tv-driver=v4l2 --tv-device=/dev/video1 --tv-input=1 --tv-norm=0 \ --vf=lavfi='[split=3 [a][b][c], [b]waveform[wfm], [c]vectorscope=color4, scale=736x736[color], [a][wfm][color] vstack=3 ]'
These result in something like this (first command is the left image, second is the right image where the same filtergraph has been used with ffmpeg, temporarily piped to ffplay for preview)
Note: vstack and hstack filters need to have the input heights/width matching, so use the scale filter if your input video has the wrong dimensions. You can also pipe a video file as seen in the left screeshot. You can find the right scale size by trial and error as vstack and hstack will tell you the widths/heights of each of the inputs if they do not match.
It seems that mpv does not cooperate if there are newlines in the filtergraph code, and the filtergraph parameter needs to be enclosed in square brackets.
Other useful tools are v4lctl and qv4l2. v4lctl allows changing the framegrabber parameters on the fly as seen here, where mpv was run first and then the two v4lctl invocations were used to fix the input and the video format (left image)
q4l2 is a program that allows you to quickly try out various settings of the card with a Qt GUI (right image)
dmesg | grep saa
[ 14.173125] saa7134: saa7130/34: v4l2 driver version 0, 2, 17 loaded [ 14.173515] saa7134: saa7134[0]: found at 0000:06:0c.0, rev: 1, irq: 18, latency: 66, mmio: 0xfca00000 [ 14.173523] saa7134: saa7134[0]: subsystem: 1131:0000, board: Philips Tiger - S Reference design [card=109,insmod option] [ 14.173559] saa7134: saa7134[0]: board init: gpio is 10000 [ 14.284270] saa7134: saa7134[0]: Huh, no eeprom present (err=-5)? [ 14.612219] saa7134: saa7134[0]: registered device video0 [v4l2] [ 14.612528] saa7134: saa7134[0]: registered device vbi0 [ 14.612779] saa7134: saa7134[0]: registered device radio0 [ 14.613802] saa7134: saa7134[1]: found at 0000:06:0d.0, rev: 1, irq: 21, latency: 66, mmio: 0xfca00400 [ 14.613812] saa7134: saa7134[1]: subsystem: 1131:0000, board: Philips Tiger - S Reference design [card=109,insmod option] [ 14.613850] saa7134: saa7134[1]: board init: gpio is 10000 [ 14.720164] saa7134: saa7134[1]: Huh, no eeprom present (err=-5)? [ 14.726553] saa7134: saa7134[1]: registered device video1 [v4l2] [ 14.726852] saa7134: saa7134[1]: registered device vbi1 [ 14.726939] saa7134: saa7134[1]: registered device radio1 [ 14.727998] saa7134: saa7134[2]: found at 0000:06:0e.0, rev: 1, irq: 22, latency: 66, mmio: 0xfca00800 [ 14.728072] saa7134: saa7134[2]: subsystem: 1131:0000, board: Philips Tiger - S Reference design [card=109,insmod option] [ 14.730487] saa7134: saa7134[2]: board init: gpio is 10000 [ 14.836166] saa7134: saa7134[2]: Huh, no eeprom present (err=-5)? [ 14.843338] saa7134: saa7134[2]: registered device video2 [v4l2] [ 14.843634] saa7134: saa7134[2]: registered device vbi2 [ 14.843716] saa7134: saa7134[2]: registered device radio2 [ 14.845232] saa7134: saa7134[3]: found at 0000:06:0f.0, rev: 1, irq: 16, latency: 66, mmio: 0xfca00c00 [ 14.845244] saa7134: saa7134[3]: subsystem: 1131:0000, board: Philips Tiger - S Reference design [card=109,insmod option] [ 14.845280] saa7134: saa7134[3]: board init: gpio is 10000 [ 14.952263] saa7134: saa7134[3]: Huh, no eeprom present (err=-5)? [ 14.958807] saa7134: saa7134[3]: registered device video3 [v4l2] [ 14.959088] saa7134: saa7134[3]: registered device vbi3 [ 14.959174] saa7134: saa7134[3]: registered device radio3 [ 15.253209] saa7134_dvb: dvb_init() allocating 1 frontend [ 15.473172] saa7134_dvb: dvb_init() allocating 1 frontend [ 15.473780] saa7134_dvb: dvb_init() allocating 1 frontend [ 15.474381] saa7134_dvb: dvb_init() allocating 1 frontend [ 15.719651] saa7134_alsa: saa7134 ALSA driver for DMA sound loaded [ 15.719729] saa7134_alsa: saa7134[0]/alsa: saa7134[0] at 0xfca00000 irq 18 registered as card -1 [ 15.727797] saa7134_alsa: saa7134[1]/alsa: saa7134[1] at 0xfca00400 irq 21 registered as card -1 [ 15.732485] saa7134_alsa: saa7134[2]/alsa: saa7134[2] at 0xfca00800 irq 22 registered as card -1 [ 15.741261] saa7134_alsa: saa7134[3]/alsa: saa7134[3] at 0xfca00c00 irq 16 registered as card -1