forked from asticode/go-astits
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dvb.go
74 lines (66 loc) · 2.56 KB
/
dvb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package astits
import (
"fmt"
"time"
"github.com/asticode/go-astikit"
)
// parseDVBTime parses a DVB time
// This field is coded as 16 bits giving the 16 LSBs of MJD followed by 24 bits coded as 6 digits in 4 - bit Binary
// Coded Decimal (BCD). If the start time is undefined (e.g. for an event in a NVOD reference service) all bits of the
// field are set to "1".
// I apologize for the computation which is really messy but details are given in the documentation
// Page: 160 | Annex C | Link: https://www.dvb.org/resources/public/standards/a38_dvb-si_specification.pdf
func parseDVBTime(i *astikit.BytesIterator) (t time.Time, err error) {
// Get next 2 bytes
var bs []byte
if bs, err = i.NextBytes(2); err != nil {
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
return
}
// Date
var mjd = uint16(bs[0])<<8 | uint16(bs[1])
var yt = int((float64(mjd) - 15078.2) / 365.25)
var mt = int((float64(mjd) - 14956.1 - float64(int(float64(yt)*365.25))) / 30.6001)
var d = int(float64(mjd) - 14956 - float64(int(float64(yt)*365.25)) - float64(int(float64(mt)*30.6001)))
var k int
if mt == 14 || mt == 15 {
k = 1
}
var y = yt + k
var m = mt - 1 - k*12
t, _ = time.Parse("06-01-02", fmt.Sprintf("%d-%d-%d", y, m, d))
// Time
var s time.Duration
if s, err = parseDVBDurationSeconds(i); err != nil {
err = fmt.Errorf("astits: parsing DVB duration seconds failed: %w", err)
return
}
t = t.Add(s)
return
}
// parseDVBDurationMinutes parses a minutes duration
// 16 bit field containing the duration of the event in hours, minutes. format: 4 digits, 4 - bit BCD = 18 bit
func parseDVBDurationMinutes(i *astikit.BytesIterator) (d time.Duration, err error) {
var bs []byte
if bs, err = i.NextBytes(2); err != nil {
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
return
}
d = parseDVBDurationByte(bs[0])*time.Hour + parseDVBDurationByte(bs[1])*time.Minute
return
}
// parseDVBDurationSeconds parses a seconds duration
// 24 bit field containing the duration of the event in hours, minutes, seconds. format: 6 digits, 4 - bit BCD = 24 bit
func parseDVBDurationSeconds(i *astikit.BytesIterator) (d time.Duration, err error) {
var bs []byte
if bs, err = i.NextBytes(3); err != nil {
err = fmt.Errorf("astits: fetching next bytes failed: %w", err)
return
}
d = parseDVBDurationByte(bs[0])*time.Hour + parseDVBDurationByte(bs[1])*time.Minute + parseDVBDurationByte(bs[2])*time.Second
return
}
// parseDVBDurationByte parses a duration byte
func parseDVBDurationByte(i byte) time.Duration {
return time.Duration(uint8(i)>>4*10 + uint8(i)&0xf)
}