func setFilter(dmxpath, dvrpath string, pids []int16) (ts.PktReader, demux.StreamFilter) { filterParam := demux.StreamFilterParam{ Pid: pids[0], In: demux.InFrontend, Out: demux.OutTSDemuxTap, Type: demux.Other, } if dvrpath != "" { filterParam.Out = demux.OutTSTap } filter, err := demux.Device(dmxpath).NewStreamFilter(&filterParam) checkErr(err) for _, pid := range pids[1:] { checkErr(filter.AddPid(pid)) } if dvrpath == "" { checkErr(filter.SetBufferSize(1024 * 188)) checkErr(filter.Start()) return ts.NewPktStreamReader(filter), filter } dvr, err := os.Open(dvrpath) checkErr(err) checkErr(filter.Start()) return ts.NewPktStreamReader(dvr), filter }
func main() { fpath := flag.String( "front", "/dev/dvb/adapter0/frontend0", "path to the frontend device", ) dmxpath := flag.String( "demux", "/dev/dvb/adapter0/demux0", "path to the demux device", ) sys := flag.String( "sys", "t", "delivery system type: t, s, s2, ca, cb, cc", ) freq := flag.Float64( "freq", 0, "frequency [Mhz]", ) sr := flag.Uint( "sr", 0, "symbol rate [kBd]", ) pol := flag.String( "pol", "h", "polarization: h, v", ) bw := flag.Uint( "bw", 0, "bandwidth [MHz] (default 0 means automatic - not supported by many tuners)", ) flag.Usage = usage flag.Parse() if flag.NArg() == 0 { usage() } pids := make([]int16, flag.NArg()) for i, a := range flag.Args() { pid, err := strconv.ParseInt(a, 0, 64) checkErr(err) if uint64(pid) > 8192 { die(a + " isn't in valid PID range [0, 8192]") } pids[i] = int16(pid) } fe, err := internal.Tune(*fpath, *sys, *pol, int64(*freq*1e6), int(*bw*1e6), *sr*1e3) checkErr(err) checkErr(internal.WaitForTune(fe, time.Now().Add(15*time.Second), true)) filterParam := demux.StreamFilterParam{ Pid: pids[0], In: demux.InFrontend, Out: demux.OutTSTap, Type: demux.Other, } filter, err = demux.Device(*dmxpath).NewStreamFilter(&filterParam) for _, pid := range pids[1:] { checkErr(filter.AddPid(pid)) } checkErr(err) checkErr(filter.Start()) var rssi, snr, ber, ublk string for { fe3 := frontend.API3{fe} if rssi != "-" { val, err := fe3.SignalStrength() if err != nil { if e, ok := err.(frontend.Error); ok && e.What == "rssi" { rssi = "-" } else { die(err.Error()) } } else { rssi = strconv.FormatInt(int64(val), 10) } } if snr != "-" { val, err := fe3.SNR() if err != nil { if e, ok := err.(frontend.Error); ok && e.What == "snr" { snr = "-" } else { die(err.Error()) } } else { snr = strconv.FormatInt(int64(val), 10) } } if ber != "-" { val, err := fe3.BER() if err != nil { if e, ok := err.(frontend.Error); ok && e.What == "ber" { ber = "-" } else { die(err.Error()) } } else { ber = strconv.FormatInt(int64(val), 10) } } if ublk != "-" { val, err := fe3.UncorrectedBlocks() if err != nil { if e, ok := err.(frontend.Error); ok && e.What == "uncorrected_blocks" { ublk = "-" } else { die(err.Error()) } } else { ublk = strconv.FormatUint(uint64(val), 10) } } log.Printf("API3 RSSI: %s SNR: %s BER: %s UBLK: %s", rssi, snr, ber, ublk) s, err := fe.Stat() checkErr(err) log.Printf( "API5 Sig: %v CNR: %v PreIFEC: %v/%v bit/bit PostIFEC: %v/%v bit/bit PostOFEC %v/%v blk/blk\n", s.Signal, s.CNR, s.PreErrBit, s.PreTotBit, s.PostErrBit, s.PostTotBit, s.ErrBlk, s.TotBlk) time.Sleep(2 * time.Second) } }
func main() { adapterPath := flag.String( "a", "/dev/dvb/adapter0", "path to the adapter directory", ) frontendPath := flag.String( "f", "frontend0", "frontend path, relative to the adapter directory", ) demuxPath := flag.String( "d", "demux0", "demux path, relative to the adapter directory", ) flag.Usage = usage flag.Parse() args := flag.Args() if len(args) < 4 { usage() os.Exit(1) } freq, err := strconv.ParseInt(args[0], 0, 64) checkErr(err) freq *= 1e6 var polar byte switch args[1] { case "v", "V": polar = 'v' case "h", "H": polar = 'h' default: die("wrong polarisation: " + args[1]) } sr, err := strconv.ParseUint(args[2], 0, 32) checkErr(err) args = args[3:] pids := make([]int16, len(args)) for i, a := range args { pid, err := strconv.ParseInt(a, 0, 64) checkErr(err) if uint64(pid) > 8192 { die(a + " isn't in valid PID range [0, 8192]") } pids[i] = int16(pid) } fe, err := frontend.Open(filepath.Join(*adapterPath, *frontendPath)) checkErr(err) checkErr(fe.SetDeliverySystem(dvb.SysDVBS2)) checkErr(fe.SetModulation(dvb.PSK8)) checkErr(fe.SetRolloff(dvb.RolloffAuto)) checkErr(fe.SetPilot(dvb.PilotAuto)) checkErr(fe.SetSymbolRate(uint32(sr * 1e3))) checkErr(fe.SetInnerFEC(dvb.FECAuto)) checkErr(fe.SetInversion(dvb.InversionAuto)) ifreq, tone, volt := frontend.SecParam(freq, rune(polar)) checkErr(fe.SetFrequency(ifreq)) checkErr(fe.SetTone(tone)) checkErr(fe.SetVoltage(volt)) checkErr(fe.Tune()) deadline := time.Now().Add(5 * time.Second) var ev frontend.Event for ev.Status()&frontend.HasLock == 0 { timedout, err := frontend.API3{fe}.WaitEvent(&ev, deadline) checkErr(err) if timedout { die("tuning timeout") } fmt.Fprintln(os.Stderr, ev.Status()) } fmt.Fprintln(os.Stderr, "tuned!") dmx := demux.Device(filepath.Join(*adapterPath, *demuxPath)) f, err := dmx.NewStreamFilter( &demux.StreamFilterParam{ Pid: pids[0], In: demux.InFrontend, Out: demux.OutTSDemuxTap, Type: demux.Other, }, ) checkErr(err) defer f.Close() for _, pid := range pids[1:] { checkErr(f.AddPid(pid)) } checkErr(f.SetBufferSize(1024 * ts.PktLen)) checkErr(f.Start()) r := ts.NewPktStreamReader(f) pkt := new(ts.ArrayPkt) for { t := time.Now() n := 4000 for i := 0; i < n; i++ { checkErr(r.ReadPkt(pkt)) } dt := time.Now().Sub(t) pps := time.Duration(n) * time.Second / dt fmt.Printf("%d pkt/s (%d kb/s)\n", pps, pps*ts.PktLen*8/1000) } }