This is a continuation of this post about my previous failures at DATV.
Debug, Defrag, Defuzz and Start Again
Okay, so Bournemouth didn’t go so well. Let’s try again - this time reading manuals and stopping to think.
The goal for this project is simple - transmit and receive a DVB-S signal.
What tools do I have available?
- CCC Camp Badge (HackRF)
- Numerous Raspberry Pis
- Laptop (Linux)
Probably a whole other pile of things
There’s a few things I know about that could use:
G0FCU’s gnuradio stack - Transmit
rpidatv - Transmit
leandvb - Receive
Cool - let’s glue all this stuff together.
So, rpidatv is really cool - it will let you transmit with the GPIO (Pin on the Raspberry Pi.That’s a super easy way to get started. It’s also got a test card mode, so I can just output stuff. Easy!
I followed the instructions on github to download and install, and then fired up the console menu -
/home/pi/rpidatv/scripts/gbmenu.sh in my case. The menu’s pretty simple to get to grips with. I picked the lowest symbol rate I could (250KS/s) and highest FEC (7⁄8, I’m expecting lots of errors or something). Test card output selected, Call Sign set up - let’s get this show on the road… Transmit!
Let’s set up leandvb on my laptop, connected to my rad1o, as before - let’s read the manual this time:
rx_sdr -f 437e6 -s 2.4e6 - | ./leandvb_tui.sh ./leandvb --fd-info 2 -f 2.4e6 --cr 7/8 --sr 250e3 --gui | vlc -
I’ve got a nice constellation, and my MER (Modulation Error Ratio) looks ok (8-9dB).
No video, though. Hm.
It tells me I’m “Searching” - I wonder why it’s not locking on to the signal.
Moved the pi back, and forward, back… forward… no luck. No better reception, even though the MER and SS are going up and down. The Test Carriers all report well and the signal appears on GQRX. So we know it’s transmitting.
Next step: Let’s attach a USB camera and use avc2ts to get some video into the system that way - maybe test cards aren’t working. No luck:
OpenMAX IL error: 0x80001000. OMX_GetHandle: 0x80001000 OMX_ErrorInsufficientResources avc2ts
I don’t even know where to start with this. Moving swiftly on…
Let’s generate the MPEG Transport Stream on my laptop and feed it into rpidatv.
Let’s use ffmpeg to capture some video and encode it to an MPEG2 Transport Stream. I stole this shamelessly from G0FCU’s aforementioned post, as this is how he generated his DVB Stream. I outputted video in from /dev/video0 (the camera) to a file. test.ts.
ffmpeg -re -thread_queue_size 1000 -i /dev/video0 -vcodec mpeg2video -s 640x480 -r 25 -b:v 2M -minrate:v 2M -maxrate:v 2M -bufsize:v 1.4M -ac 2 -b:a 48k -mpegts_transport_stream_id 1025 -mpegts_service_id 1 -mpegts_pmt_start_pid 0x0fff -mpegts_start_pid 0x0121 -muxrate 2M -f mpegts -y test.ts
This was SCP’d to the Raspberry Pi and played.
Success, kind of. A very, very occasional lock and a little bit of blocky video would play on vlc. I wonder, what am I doing wrong?
I dunno - it was closing time at the hackerspace and I had just transmitted without a callsign accidentally, probably bedtime.
Day two brings a clear head and some thoughts bouncing about in the head. And a 3 hour drive to think about my feelings. The transmit and receive paths are more or less right - the hardware is doing as I expect, just not very well.
Let’s not assume hardware failure… Let’s start to look at the parameters I give the system.
First off, we’ll need a longer video, and mark it with a callsign. Let’s get Big Buck Bunny, because it’s free (Creative Commons), and use ffmpeg to write and overlay…
My overlay is shamelessly stolen from Chris MW0LLK’s post that explains how to use ffmpeg to generate a transport stream. Admittedly it’s mostly windows focussed, but it’s pretty great nonetheless.
It also reveals how you can embed program information in the transport stream. Of course you can! How else do you get this stuff in? The ffmpeg command ends up looking like:
ffmpeg -re -thread_queue_size 1000 -i Videos/big_buck_bunny_480p_surround-fix.avi -vcodec mpeg2video -s 640x480 -r 25 -acodec mp2 -b:v 2M -minrate:v 2M -maxrate:v 2M -bufsize:v 2M -ac 2 -b:a 48k -mpegts_transport_stream_id 1025 -mpegts_service_id 1 -mpegts_pmt_start_pid 0x0fff -mpegts_start_pid 0x0121 -muxrate 2M -metadata service_provider="MM3ZRZ" -metadata service_name="Big Buck Bunny" -f mpegts -vf "drawtext=fontfile='/usr/share/fonts/truetype/freefont/FreeSans.ttf':text='MM3ZRZ-70cm DATV':x=60:y=34:fontsize=20:fontcolor=0xffffff7f" -y test2.ts
You can see my overlay in FreeSans - MM3ZRZ-70cm DATV. You can see my Service Provider information and Serice Name set also - cool! Keeping the bitrate at 2MBit/s, that’s a decent bit rate. I’ve got sound now too - great.
Generate 30s of footage and SCP it.
Fire up the transmitter, get the same issue. Bits of video. Hmm. Something’s not right.
Once upon a time, I was well educated. Sometimes it bounces back into my head. Symbol rates. Bandwidths. Codes. FEC. They’re all interconnected. Of course they are - the more symbols you send per second, the more bandwidth you need. Encoding has an effect. FEC adds or removes overhead. Of course it does.
250KSym/s is nowhere near enough for a 2MBit stream. Not at all. How do I know? W6ZE Tech talk #76 is the best resource I’ve found to explain this… It has the equations and the explanations of everything you need to know. My numbers work out to: Bit Rate of 2MBit/s FEC 7⁄8 - Symbol Rate of 1.241MS/s and Bandwidth of ~1.651MHz. Yeah. 250KSym/s is nowehere near enough.
The sample rate was set wider than needed, the symbol rate was set on the nose… The system mostly works! First time!
rx_sdr -f 437e6 -s 2.4e6 - | ./leandvb_tui.sh ./leandvb --fd-info 2 -f 2.4e6 --cr 7/8 --sr 1.241e6 --gui | vlc -
The video’s a little sketchy, some bits and blocks - let’s retune and refine the system.
First off, let’s up the Symbol Rate to 1400 - the video gets clearer. Good.
Next off, let’s look at the video encoder - it’s spitting errors:
dts<pcr Stream Invalid
But watching the encode detail translates this for me - the mpeg transport stream is bigger than the hard limit i’ve set (2MBit).
Reducing the video bitrate should control this -
ffmpeg -re -thread_queue_size 1000 -i Videos/big_buck_bunny_480p_surround-fix.avi -vcodec mpeg2video -s 640x480 -r 25 -acodec mp2 -b:v 1.5M -minrate:v 1.5M -maxrate:v 1.5M -bufsize:v 2M -ac 2 -b:a 128k -mpegts_transport_stream_id 1025 -mpegts_service_id 1 -mpegts_pmt_start_pid 0x0fff -mpegts_start_pid 0x0121 -muxrate 2M -metadata service_provider="MM3ZRZ" -metadata service_name="Big Buck Bunny" -f mpegts -vf "drawtext=fontfile='/usr/share/fonts/truetype/freefont/FreeSans.ttf':text='MM3ZRZ-70cm DATV':x=60:y=34:fontsize=20:fontcolor=0xffffff7f" -y test2.ts
With video maximum rate kept at 1.5MBit/s, the stream never steps over 2MBit/s, which is perfect!
The video transmits and receives almost perfectly - that’s good enough for me! Note in the image below my overlay and program information working!
Conclusion & Future Work
So there’s lots to do here. I’d like to connect the I/Q output from rpidatv to a hackrf. That gives me a lot more flexibility in frequencies and, importantly, filtering. It also lets me connect to power amplifiers and create a better system for portable operation. I wonder what glue this will need.
I need to work out why sending the exactly correct maximum symbol rate doesn’t work perfectly too - I wonder what I’m missing. Maybe the signal needs a little roll off area, so it’s actually wider than I think it should be. Hmmmmmm.
Generating the transport stream live on the Raspberry Pi would be good too - can avc2ts be used to do this? Not currently, unless it’s playing on the pi screen. Maybe I’ll need to give F5OEO a prod and see.