streaming

Media streaming and broadcast systems in Go
Log | Files | Refs | README | LICENSE

session.go (1778B)


      1 package rtp
      2 
      3 import (
      4 	"fmt"
      5 	"math/rand"
      6 	"net"
      7 	"time"
      8 )
      9 
     10 func Dial(network, addr string) (*Session, error) {
     11 	conn, err := net.Dial(network, addr)
     12 	if err != nil {
     13 		return nil, err
     14 	}
     15 	s := Session{conn: conn}
     16 	s.init()
     17 	return &s, nil
     18 }
     19 
     20 // Session represents a RTP session...
     21 // When a Session is established with Dial(), ...
     22 // TODO(otl): what does session automatically handle? what do we not
     23 // need to set in each packets header?
     24 type Session struct {
     25 	// Clock is the rate of the... in hertz.
     26 	// If zero, automatic detection attempted...
     27 	Clock int
     28 
     29 	conn       net.Conn
     30 	sequence   uint16
     31 	timestamp  uint32
     32 	previous   time.Time
     33 	syncSource uint32
     34 }
     35 
     36 func (s *Session) init() {
     37 	s.sequence = uint16(rand.Intn(0xffff)) // max uint16
     38 	s.syncSource = rand.Uint32()
     39 	s.timestamp = rand.Uint32()
     40 }
     41 
     42 // Transmit sends the packet to the destination address in s.
     43 //
     44 // TODO(otl): some fields in packet's header are set by Transmit.
     45 // Which ones? Otherwise people are going to get surprised!
     46 func (s *Session) Transmit(packet *Packet) error {
     47 	if packet.Header.Version == 0 {
     48 		packet.Header.Version = VersionRFC3550
     49 	}
     50 
     51 	s.sequence++
     52 	packet.Header.Sequence = s.sequence
     53 
     54 	ticks := ticksSince(s.previous, s.Clock)
     55 	packet.Header.Timestamp = s.timestamp + ticks
     56 	s.previous = time.Now()
     57 	s.timestamp += ticks
     58 
     59 	packet.Header.SyncSource = s.syncSource
     60 
     61 	b, err := Marshal(packet)
     62 	if err != nil {
     63 		return fmt.Errorf("marshal packet: %w", err)
     64 	}
     65 	n, err := s.conn.Write(b)
     66 	if n != len(b) {
     67 		if err != nil {
     68 			return fmt.Errorf("short write %d bytes: %w", n, err)
     69 		}
     70 		return fmt.Errorf("short write (%d bytes)", n)
     71 	}
     72 	return err
     73 }
     74 
     75 func ticksSince(t time.Time, clockRate int) (ticks uint32) {
     76 	dur := int(time.Since(t)/time.Second) * clockRate
     77 	return uint32(dur)
     78 }