test dvrip

This commit is contained in:
Andrey Semochkin 2021-05-23 13:37:05 +03:00
parent 5adbbcc01f
commit 5b25bda1a0
6 changed files with 895 additions and 11 deletions

502
format/dvrip/client.go Normal file
View File

@ -0,0 +1,502 @@
package dvrip
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"html"
"net"
"net/url"
"strconv"
"strings"
"time"
"github.com/deepch/vdk/av"
"github.com/deepch/vdk/codec"
"github.com/deepch/vdk/codec/h264parser"
)
const (
SignalStreamStop = iota
SignalCodecUpdate
)
type Client struct {
conn net.Conn
login string
password string
host string
stream string
sequenceNumber int32
session int32
aliveInterval time.Duration
CodecData []av.CodecData
OutgoingPacketQueue chan *av.Packet
Signals chan int
options ClientOptions
sps []byte
pps []byte
}
type ClientOptions struct {
Debug bool
URL string
DialTimeout time.Duration
ReadWriteTimeout time.Duration
DisableAudio bool
}
//Dial func
func Dial(options ClientOptions) (*Client, error) {
client := &Client{
Signals: make(chan int, 100),
OutgoingPacketQueue: make(chan *av.Packet, 3000),
options: options,
}
err := client.parseURL(html.UnescapeString(client.options.URL))
if err != nil {
return nil, err
}
client.conn, err = net.DialTimeout("tcp", client.host, time.Second*2)
if err != nil {
return nil, err
}
err = client.conn.SetDeadline(time.Now().Add(5 * time.Second))
if err != nil {
return nil, err
}
err = client.Login()
if err != nil {
return nil, err
}
err = client.SetTime()
if err != nil {
return nil, err
}
go client.Monitor()
return client, nil
}
//Close func
func (client *Client) Close() error {
err := client.conn.Close()
return err
}
//SetKeepAlive func
func (client *Client) SetKeepAlive() error {
body, err := json.Marshal(map[string]string{
"Name": "KeepAlive",
"SessionID": fmt.Sprintf("0x%08X", client.session),
})
if err != nil {
return err
}
err = client.send(codeKeepAlive, body)
if err != nil {
return err
}
return nil
}
//Monitor func
func (client *Client) Monitor() {
defer func() {
client.Signals <- SignalStreamStop
}()
_, _, err := client.Command(codeOPMonitor, map[string]interface{}{
"Action": "Claim",
"Parameter": map[string]interface{}{
"Channel": 0,
"CombinMode": "NONE",
"StreamType": client.stream,
"TransMode": "TCP",
},
})
if err != nil {
return
}
payload, err := json.Marshal(map[string]interface{}{
"Name": "OPMonitor",
"SessionID": fmt.Sprintf("0x%08X", client.session),
"OPMonitor": map[string]interface{}{
"Action": "Start",
"Parameter": map[string]interface{}{
"Channel": 0,
"CombinMode": "NONE",
"StreamType": client.stream,
"TransMode": "TCP",
},
},
})
err = client.send(1410, payload)
if err != nil {
return
}
var length uint32 = 0
var dataType uint32
timer := time.Now()
var fps int
for {
if time.Now().Sub(timer).Milliseconds() > client.aliveInterval.Milliseconds() {
err = client.SetKeepAlive()
if err != nil {
return
}
timer = time.Now()
}
_, body, err := client.recv(false)
if err != nil {
return
}
buf := bytes.NewReader(body)
err = binary.Read(buf, binary.BigEndian, &dataType)
if err != nil {
return
}
switch dataType {
case 0x1FC, 0x1FE:
frame := struct {
Media byte
FPS byte
Width byte
Height byte
DateTime uint32
Length uint32
}{}
err = binary.Read(buf, binary.LittleEndian, &frame)
fps = int(frame.FPS)
if err != nil {
return
}
var packet bytes.Buffer
if frame.Length > uint32(buf.Len()) {
need := frame.Length - uint32(buf.Len())
_, err = buf.WriteTo(&packet)
if err != nil {
return
}
_, err := client.recvSize(&packet, need)
if err != nil {
return
}
} else {
_, err = buf.WriteTo(&packet)
if err != nil {
return
}
}
if parseMediaType(dataType, frame.Media) == av.H264.String() {
packets, _ := h264parser.SplitNALUs(packet.Bytes())
for _, i2 := range packets {
naluType := i2[0] & 0x1f
switch {
case naluType >= 1 && naluType <= 5:
client.OutgoingPacketQueue <- &av.Packet{Duration: time.Duration(1000/fps) * time.Millisecond, Idx: 0, IsKeyFrame: naluType == 5, Data: append(binSize(len(i2)), i2...)}
case naluType == 7:
client.CodecUpdateSPS(i2)
case naluType == 8:
client.CodecUpdatePPS(i2)
}
}
}
case 0x1FD:
err = binary.Read(buf, binary.LittleEndian, &length)
if err != nil {
return
}
var packet bytes.Buffer
if length > uint32(buf.Len()) {
need := length - uint32(buf.Len())
_, err = buf.WriteTo(&packet)
if err != nil {
return
}
_, err := client.recvSize(&packet, need)
if err != nil {
return
}
} else {
_, err = buf.WriteTo(&packet)
if err != nil {
return
}
}
packets, _ := h264parser.SplitNALUs(packet.Bytes())
for _, i2 := range packets {
naluType := i2[0] & 0x1f
switch {
case naluType >= 1 && naluType <= 5:
if fps != 0 {
client.OutgoingPacketQueue <- &av.Packet{Duration: time.Duration(1000/fps) * time.Millisecond, Idx: 0, IsKeyFrame: naluType == 5, Data: append(binSize(len(i2)), i2...)}
}
case naluType == 7:
client.CodecUpdateSPS(i2)
case naluType == 8:
client.CodecUpdatePPS(i2)
}
}
case 0x1FA, 0x1F9:
if client.options.DisableAudio {
continue
}
frame := struct {
Media byte
SampleRate byte
Length uint16
}{}
err = binary.Read(buf, binary.LittleEndian, &frame)
if err != nil {
return
}
var packet bytes.Buffer
if uint32(frame.Length) > uint32(buf.Len()) {
need := uint32(frame.Length) - uint32(buf.Len())
_, err = buf.WriteTo(&packet)
if err != nil {
return
}
_, err := client.recvSize(&packet, need)
if err != nil {
return
}
} else {
_, err = buf.WriteTo(&packet)
if err != nil {
return
}
}
if parseMediaType(dataType, frame.Media) == av.PCM_ALAW.String() {
if client.CodecData != nil {
if len(client.CodecData) == 1 {
client.CodecUpdatePCMAlaw()
}
client.OutgoingPacketQueue <- &av.Packet{Duration: time.Duration(8000/packet.Len()) * time.Millisecond, Idx: 1, Data: packet.Bytes()}
}
}
case 0xFFD8FFE0:
default:
continue
}
}
}
func (client *Client) SetTime() error {
_, _, err := client.Command(codeOPTimeSetting, time.Now().Format("2006-01-02 15:04:05"))
return err
}
func (client *Client) Login() error {
body, err := json.Marshal(map[string]string{
"EncryptType": "MD5",
"LoginType": "DVRIP-WEB",
"PassWord": sofiaHash(client.password),
"UserName": client.login,
})
if err != nil {
return err
}
err = client.send(codeLogin, body)
if err != nil {
return err
}
_, resp, err := client.recv(true)
if err != nil {
return err
}
res := LoginResp{}
err = json.Unmarshal(resp, &res)
if err != nil {
return err
}
if (statusCode(res.Ret) != statusOK) && (statusCode(res.Ret) != statusUpgradeSuccessful) {
return fmt.Errorf("unexpected status code: %v - %v", res.Ret, statusCodes[statusCode(res.Ret)])
}
client.aliveInterval = time.Duration(res.AliveInterval) * time.Second
session, err := strconv.ParseUint(res.SessionID, 0, 32)
if err != nil {
return err
}
client.session = int32(session)
return nil
}
//Command func
func (client *Client) Command(command requestCode, data interface{}) (*Payload, []byte, error) {
params, err := json.Marshal(map[string]interface{}{
"Name": requestCodes[command],
"SessionID": fmt.Sprintf("0x%08X", client.session),
requestCodes[command]: data,
})
if err != nil {
return nil, nil, err
}
err = client.send(command, params)
if err != nil {
return nil, nil, err
}
resp, body, err := client.recv(true)
return resp, body, err
}
//send func
func (client *Client) send(msgID requestCode, data []byte) error {
var buf bytes.Buffer
if err := binary.Write(&buf, binary.LittleEndian, Payload{
Head: 255,
Version: 0,
Session: client.session,
SequenceNumber: client.sequenceNumber,
MsgID: int16(msgID),
BodyLength: int32(len(data)) + 2,
}); err != nil {
return err
}
err := client.conn.SetDeadline(time.Now().Add(5 * time.Second))
if err != nil {
return err
}
err = binary.Write(&buf, binary.LittleEndian, data)
if err != nil {
return err
}
err = binary.Write(&buf, binary.LittleEndian, magicEnd)
if err != nil {
return err
}
_, err = client.conn.Write(buf.Bytes())
if err != nil {
return err
}
client.sequenceNumber++
return nil
}
//recvSize func
func (client *Client) recvSize(buffer *bytes.Buffer, size uint32) ([]byte, error) {
all := uint32(0)
for {
_, body, err := client.recv(false)
if err != nil {
return nil, err
}
all += uint32(len(body))
buffer.Write(body)
if all == size {
break
} else if all > size {
return nil, fmt.Errorf("invalid read size")
}
}
return nil, nil
}
//recv func
func (client *Client) recv(text bool) (*Payload, []byte, error) {
var p Payload
var b = make([]byte, 20)
err := client.conn.SetReadDeadline(time.Now().Add(5 * time.Second))
if err != nil {
return nil, nil, err
}
_, err = client.conn.Read(b)
if err != nil {
return nil, nil, err
}
err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &p)
if err != nil {
return nil, nil, err
}
client.sequenceNumber += 1
if p.BodyLength <= 0 || p.BodyLength >= 100000 {
return nil, nil, fmt.Errorf("invalid bodylength: %v", p.BodyLength)
}
body := make([]byte, p.BodyLength)
err = binary.Read(client.conn, binary.LittleEndian, &body)
if err != nil {
return nil, nil, err
}
if text && len(body) > 2 && bytes.Compare(body[len(body)-2:], []byte{10, 0}) == 0 {
body = body[:len(body)-2]
}
return &p, body, nil
}
//parseURL func
func (client *Client) parseURL(rawURL string) error {
l, err := url.Parse(rawURL)
if err != nil {
return err
}
username := l.User.Username()
password, _ := l.User.Password()
l.User = nil
if l.Port() == "" {
l.Host = fmt.Sprintf("%s:%s", l.Host, "34567")
}
if username == "" {
username = "admin"
}
if password == "" {
password = "admin"
}
client.login = username
client.password = password
client.host = l.Host
client.stream = strings.Trim(l.EscapedPath(), "/")
return nil
}
func (client *Client) CodecUpdateSPS(val []byte) {
if bytes.Compare(val, client.sps) == 0 {
return
}
client.sps = val
if len(client.pps) == 0 {
return
}
codecData, err := h264parser.NewCodecDataFromSPSAndPPS(val, client.pps)
if err != nil {
return
}
if len(client.CodecData) > 0 {
for i, i2 := range client.CodecData {
if i2.Type().IsVideo() {
client.CodecData[i] = codecData
}
}
} else {
client.CodecData = append(client.CodecData, codecData)
}
client.Signals <- SignalCodecUpdate
}
func (client *Client) CodecUpdatePPS(val []byte) {
if bytes.Compare(val, client.pps) == 0 {
return
}
client.pps = val
if len(client.sps) == 0 {
return
}
codecData, err := h264parser.NewCodecDataFromSPSAndPPS(client.sps, val)
if err != nil {
return
}
if len(client.CodecData) > 0 {
for i, i2 := range client.CodecData {
if i2.Type().IsVideo() {
client.CodecData[i] = codecData
}
}
} else {
client.CodecData = append(client.CodecData, codecData)
}
client.Signals <- SignalCodecUpdate
}
func (client *Client) CodecUpdatePCMAlaw() {
CodecData := codec.NewPCMAlawCodecData()
client.CodecData = append(client.CodecData, CodecData)
client.Signals <- SignalCodecUpdate
}

185
format/dvrip/struct.go Normal file
View File

@ -0,0 +1,185 @@
package dvrip
import (
"crypto/md5"
"encoding/binary"
"time"
)
var magicEnd = [2]byte{0x0A, 0x00}
const alnum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
type Payload struct {
Head byte
Version byte
_ byte
_ byte
Session int32
SequenceNumber int32
_ byte
_ byte
MsgID int16
BodyLength int32
}
type LoginResp struct {
AliveInterval int `json:"AliveInterval"`
ChannelNum int `json:"ChannelNum"`
DeviceType string `json:"DeviceType "`
ExtraChannel int `json:"ExtraChannel"`
Ret int `json:"Ret"`
SessionID string `json:"SessionID"`
}
type requestCode uint16
const (
codeLogin requestCode = 1000
codeKeepAlive requestCode = 1006
codeSystemInfo requestCode = 1020
codeNetWorkNetCommon requestCode = 1042
codeGeneral requestCode = 1042
codeChannelTitle requestCode = 1046
codeSystemFunction requestCode = 1360
codeEncodeCapability requestCode = 1360
codeOPPTZControl requestCode = 1400
codeOPMonitor requestCode = 1413
codeOPTalk requestCode = 1434
codeOPTimeSetting requestCode = 1450
codeOPMachine requestCode = 1450
codeOPTimeQuery requestCode = 1452
codeAuthorityList requestCode = 1470
codeUsers requestCode = 1472
codeGroups requestCode = 1474
codeAddGroup requestCode = 1476
codeModifyGroup requestCode = 1478
codeDelGroup requestCode = 1480
codeAddUser requestCode = 1482
codeModifyUser requestCode = 1484
codeDelUser requestCode = 1486
codeModifyPassword requestCode = 1488
codeAlarmSet requestCode = 1500
codeOPNetAlarm requestCode = 1506
codeAlarmInfo requestCode = 1504
codeOPSendFile requestCode = 1522
codeOPSystemUpgrade requestCode = 1525
codeOPNetKeyboard requestCode = 1550
codeOPSNAP requestCode = 1560
codeOPMailTest requestCode = 1636
)
type statusCode int
const (
statusOK statusCode = 100
statusUnknownError statusCode = 101
statusUnsupportedVersion statusCode = 102
statusRequestNotPermitted statusCode = 103
statusUserAlreadyLoggedIn statusCode = 104
statusUserIsNotLoggedIn statusCode = 105
statusUsernameOrPasswordIsIncorrect statusCode = 106
statusUserDoesNotHaveNecessaryPermissions statusCode = 107
statusPasswordIsIncorrect statusCode = 203
statusStartOfUpgrade statusCode = 511
statusUpgradeWasNotStarted statusCode = 512
statusUpgradeDataErrors statusCode = 513
statusUpgradeError statusCode = 514
statusUpgradeSuccessful statusCode = 515
)
var statusCodes = map[statusCode]string{
statusOK: "OK",
statusUnknownError: "Unknown error",
statusUnsupportedVersion: "Unsupported version",
statusRequestNotPermitted: "Request not permitted",
statusUserAlreadyLoggedIn: "User already logged in",
statusUserIsNotLoggedIn: "User is not logged in",
statusUsernameOrPasswordIsIncorrect: "Username or password is incorrect",
statusUserDoesNotHaveNecessaryPermissions: "User does not have necessary permissions",
statusPasswordIsIncorrect: "Password is incorrect",
statusStartOfUpgrade: "Start of upgrade",
statusUpgradeWasNotStarted: "Upgrade was not started",
statusUpgradeDataErrors: "Upgrade data errors",
statusUpgradeError: "Upgrade error",
statusUpgradeSuccessful: "Upgrade successful",
}
var requestCodes = map[requestCode]string{
codeOPMonitor: "OPMonitor",
codeOPTimeSetting: "OPTimeSetting",
}
type MetaInfo struct {
Width int
Height int
Datetime time.Time
FPS int
Frame string
Type string
}
type Frame struct {
Data []byte
Meta MetaInfo
}
//sofiaHash func
func sofiaHash(password string) string {
digest := md5.Sum([]byte(password))
hash := make([]byte, 0, 8)
for i := 1; i < len(digest); i += 2 {
sum := int(digest[i-1]) + int(digest[i])
hash = append(hash, alnum[sum%len(alnum)])
}
return string(hash)
}
//parseMediaType func
func parseMediaType(dataType uint32, mediaCode byte) string {
switch dataType {
case 0x1FC, 0x1FD:
switch mediaCode {
case 1:
return "MPEG4"
case 2:
return "H264"
case 3:
return "H265"
}
case 0x1F9:
if mediaCode == 1 || mediaCode == 6 {
return "info"
}
case 0x1FA:
if mediaCode == 0xE {
return "PCM_ALAW"
}
case 0x1FE:
if mediaCode == 0 {
return "JPEG"
}
default:
return "unknown"
}
return "unexpected"
}
//parseDatetime func
func parseDatetime(value uint32) time.Time {
second := int(value & 0x3F)
minute := int((value & 0xFC0) >> 6)
hour := int((value & 0x1F000) >> 12)
day := int((value & 0x3E0000) >> 17)
month := int((value & 0x3C00000) >> 22)
year := int(((value & 0xFC000000) >> 26) + 2000)
return time.Date(year, time.Month(month), day, hour, minute, second, 0, time.UTC)
}
//binSize func
func binSize(val int) []byte {
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, uint32(val))
return buf
}

View File

@ -3820,3 +3820,103 @@ func (self *TrackFragDecodeTime) Unmarshal(b []byte, offset int) (n int, err err
func (self TrackFragDecodeTime) Children() (r []Atom) {
return
}
const FTYP = Tag(0x66747970)
type FileType struct {
MajorBrand uint32
MinorVersion uint32
CompatibleBrands []uint32
AtomPos
}
func (t FileType) Tag() Tag {
return FTYP
}
func (f FileType) Marshal(b []byte) (n int) {
l := 16 + 4*len(f.CompatibleBrands)
pio.PutU32BE(b, uint32(l))
pio.PutU32BE(b[4:], uint32(FTYP))
pio.PutU32BE(b[8:], f.MajorBrand)
pio.PutU32BE(b[12:], f.MinorVersion)
for i, v := range f.CompatibleBrands {
pio.PutU32BE(b[16+4*i:], v)
}
return l
}
func (f FileType) Len() int {
return 16 + 4*len(f.CompatibleBrands)
}
func (f *FileType) Unmarshal(b []byte, offset int) (n int, err error) {
f.AtomPos.setPos(offset, len(b))
n = 8
if len(b) < n+8 {
return 0, parseErr("MajorBrand", offset+n, nil)
}
f.MajorBrand = pio.U32BE(b[n:])
n += 4
f.MinorVersion = pio.U32BE(b[n:])
n += 4
for n < len(b)-3 {
f.CompatibleBrands = append(f.CompatibleBrands, pio.U32BE(b[n:]))
n += 4
}
return
}
func (f FileType) Children() []Atom {
return nil
}
const STYP = Tag(0x73747970)
type SegmentType struct {
MajorBrand uint32
MinorVersion uint32
CompatibleBrands []uint32
AtomPos
}
func (t SegmentType) Tag() Tag {
return STYP
}
func (f SegmentType) Marshal(b []byte) (n int) {
l := 16 + 4*len(f.CompatibleBrands)
pio.PutU32BE(b, uint32(l))
pio.PutU32BE(b[4:], uint32(STYP))
pio.PutU32BE(b[8:], f.MajorBrand)
pio.PutU32BE(b[12:], f.MinorVersion)
for i, v := range f.CompatibleBrands {
pio.PutU32BE(b[16+4*i:], v)
}
return l
}
func (f SegmentType) Len() int {
return 16 + 4*len(f.CompatibleBrands)
}
func (f *SegmentType) Unmarshal(b []byte, offset int) (n int, err error) {
f.AtomPos.setPos(offset, len(b))
n = 8
if len(b) < n+8 {
return 0, parseErr("MajorBrand", offset+n, nil)
}
f.MajorBrand = pio.U32BE(b[n:])
n += 4
f.MinorVersion = pio.U32BE(b[n:])
n += 4
for n < len(b)-3 {
f.CompatibleBrands = append(f.CompatibleBrands, pio.U32BE(b[n:]))
n += 4
}
return
}
func (f SegmentType) Children() []Atom {
return nil
}

View File

@ -3820,3 +3820,103 @@ func (self *TrackFragDecodeTime) Unmarshal(b []byte, offset int) (n int, err err
func (self TrackFragDecodeTime) Children() (r []Atom) {
return
}
const FTYP = Tag(0x66747970)
type FileType struct {
MajorBrand uint32
MinorVersion uint32
CompatibleBrands []uint32
AtomPos
}
func (t FileType) Tag() Tag {
return FTYP
}
func (f FileType) Marshal(b []byte) (n int) {
l := 16 + 4*len(f.CompatibleBrands)
pio.PutU32BE(b, uint32(l))
pio.PutU32BE(b[4:], uint32(FTYP))
pio.PutU32BE(b[8:], f.MajorBrand)
pio.PutU32BE(b[12:], f.MinorVersion)
for i, v := range f.CompatibleBrands {
pio.PutU32BE(b[16+4*i:], v)
}
return l
}
func (f FileType) Len() int {
return 16 + 4*len(f.CompatibleBrands)
}
func (f *FileType) Unmarshal(b []byte, offset int) (n int, err error) {
f.AtomPos.setPos(offset, len(b))
n = 8
if len(b) < n+8 {
return 0, parseErr("MajorBrand", offset+n, nil)
}
f.MajorBrand = pio.U32BE(b[n:])
n += 4
f.MinorVersion = pio.U32BE(b[n:])
n += 4
for n < len(b)-3 {
f.CompatibleBrands = append(f.CompatibleBrands, pio.U32BE(b[n:]))
n += 4
}
return
}
func (f FileType) Children() []Atom {
return nil
}
const STYP = Tag(0x73747970)
type SegmentType struct {
MajorBrand uint32
MinorVersion uint32
CompatibleBrands []uint32
AtomPos
}
func (t SegmentType) Tag() Tag {
return STYP
}
func (f SegmentType) Marshal(b []byte) (n int) {
l := 16 + 4*len(f.CompatibleBrands)
pio.PutU32BE(b, uint32(l))
pio.PutU32BE(b[4:], uint32(STYP))
pio.PutU32BE(b[8:], f.MajorBrand)
pio.PutU32BE(b[12:], f.MinorVersion)
for i, v := range f.CompatibleBrands {
pio.PutU32BE(b[16+4*i:], v)
}
return l
}
func (f SegmentType) Len() int {
return 16 + 4*len(f.CompatibleBrands)
}
func (f *SegmentType) Unmarshal(b []byte, offset int) (n int, err error) {
f.AtomPos.setPos(offset, len(b))
n = 8
if len(b) < n+8 {
return 0, parseErr("MajorBrand", offset+n, nil)
}
f.MajorBrand = pio.U32BE(b[n:])
n += 4
f.MinorVersion = pio.U32BE(b[n:])
n += 4
for n < len(b)-3 {
f.CompatibleBrands = append(f.CompatibleBrands, pio.U32BE(b[n:]))
n += 4
}
return
}
func (f SegmentType) Children() []Atom {
return nil
}

View File

@ -871,6 +871,8 @@ func (client *RTSPClient) Println(v ...interface{}) {
log.Println(v)
}
}
//binSize
func binSize(val int) []byte {
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, uint32(val))

View File

@ -2,9 +2,10 @@ package tsio
import (
"fmt"
"github.com/deepch/vdk/utils/bits/pio"
"io"
"time"
"github.com/deepch/vdk/utils/bits/pio"
)
const (
@ -513,6 +514,7 @@ func NewTSWriter(pid uint16) *TSWriter {
}
return w
}
//TSHeader func
type TSHeader struct {
PID uint
@ -524,6 +526,7 @@ type TSHeader struct {
RandomAccessIndicator bool
HeaderLength uint
}
//WriteTSHeader func
func WriteTSHeader(w io.Writer, element TSHeader, dataLength int) (written int, err error) {
var flags, extFlags uint
@ -614,15 +617,6 @@ func (self *TSWriter) WritePackets(w io.Writer, datav [][]byte, pcr time.Duratio
self.tshdr[3] = byte(self.ContinuityCounter)&0xf | 0x30
self.tshdr[5] = 0 // flags
hdrlen := 6
//pid := uint16((self.tshdr[1]&0x1f))<<8 | uint16(self.tshdr[2])
//if pid != 256 {
//self.tshdr[3] = 0x01
//self.tshdr[3] = 0x47
//self.tshdr[4]
// log.Println(self.tshdr[:5])
// log.Println("pid", pid,self.tshdr[3] )
//}
self.ContinuityCounter++
if writepos == 0 {
@ -716,9 +710,10 @@ func WriteUInt64(w io.Writer, val uint64, n int) (err error) {
func WriteUInt(w io.Writer, val uint, n int) (err error) {
return WriteUInt64(w, uint64(val), n)
}
//PCRToUInt func
func PCRToUInt(pcr uint64) uint64 {
base := pcr / 300
ext := pcr % 300
return base<<15 | 0x3f<<9 | ext
}
}