Browse Source

RTMP client: move writing of track info into WriteMetadata()

pull/340/head
aler9 4 years ago
parent
commit
ede82808bb
  1. 51
      internal/clientrtmp/client.go
  2. 8
      internal/rtmp/aac.go
  3. 22
      internal/rtmp/h264.go
  4. 58
      internal/rtmp/metadata.go

51
internal/clientrtmp/client.go

@ -88,11 +88,7 @@ type Client struct {
pathMan PathMan pathMan PathMan
parent Parent parent Parent
// read mode only // read mode
h264Decoder *rtph264.Decoder
videoTrack *gortsplib.Track
aacDecoder *rtpaac.Decoder
audioTrack *gortsplib.Track
ringBuffer *ringbuffer.RingBuffer ringBuffer *ringbuffer.RingBuffer
// in // in
@ -225,10 +221,9 @@ func (c *Client) runRead() {
} }
var videoTrack *gortsplib.Track var videoTrack *gortsplib.Track
var h264SPS []byte var h264Decoder *rtph264.Decoder
var h264PPS []byte
var audioTrack *gortsplib.Track var audioTrack *gortsplib.Track
var aacConfig []byte var aacDecoder *rtpaac.Decoder
err = func() error { err = func() error {
for i, t := range tracks { for i, t := range tracks {
@ -236,25 +231,18 @@ func (c *Client) runRead() {
if videoTrack != nil { if videoTrack != nil {
return fmt.Errorf("can't read track %d with RTMP: too many tracks", i+1) return fmt.Errorf("can't read track %d with RTMP: too many tracks", i+1)
} }
videoTrack = t
var err error videoTrack = t
h264SPS, h264PPS, err = t.ExtractDataH264() h264Decoder = rtph264.NewDecoder()
if err != nil {
return err
}
} else if t.IsAAC() { } else if t.IsAAC() {
if audioTrack != nil { if audioTrack != nil {
return fmt.Errorf("can't read track %d with RTMP: too many tracks", i+1) return fmt.Errorf("can't read track %d with RTMP: too many tracks", i+1)
} }
audioTrack = t
var err error audioTrack = t
aacConfig, err = t.ExtractDataAAC() clockRate, _ := audioTrack.ClockRate()
if err != nil { aacDecoder = rtpaac.NewDecoder(clockRate)
return err
}
} }
} }
@ -265,21 +253,6 @@ func (c *Client) runRead() {
c.conn.NetConn().SetWriteDeadline(time.Now().Add(c.writeTimeout)) c.conn.NetConn().SetWriteDeadline(time.Now().Add(c.writeTimeout))
c.conn.WriteMetadata(videoTrack, audioTrack) c.conn.WriteMetadata(videoTrack, audioTrack)
if videoTrack != nil {
c.conn.NetConn().SetWriteDeadline(time.Now().Add(c.writeTimeout))
c.conn.WriteH264Config(h264SPS, h264PPS)
c.h264Decoder = rtph264.NewDecoder()
c.videoTrack = videoTrack
}
if audioTrack != nil {
c.conn.NetConn().SetWriteDeadline(time.Now().Add(c.writeTimeout))
c.conn.WriteAACConfig(aacConfig)
clockRate, _ := audioTrack.ClockRate()
c.aacDecoder = rtpaac.NewDecoder(clockRate)
c.audioTrack = audioTrack
}
c.ringBuffer = ringbuffer.New(uint64(c.readBufferCount)) c.ringBuffer = ringbuffer.New(uint64(c.readBufferCount))
resc := make(chan client.PlayRes) resc := make(chan client.PlayRes)
@ -325,8 +298,8 @@ func (c *Client) runRead() {
now := time.Now() now := time.Now()
if c.videoTrack != nil && pair.trackID == c.videoTrack.ID { if videoTrack != nil && pair.trackID == videoTrack.ID {
nts, err := c.h264Decoder.Decode(pair.buf) nts, err := h264Decoder.Decode(pair.buf)
if err != nil { if err != nil {
if err != rtph264.ErrMorePacketsNeeded { if err != rtph264.ErrMorePacketsNeeded {
c.log(logger.Warn, "unable to decode video track: %v", err) c.log(logger.Warn, "unable to decode video track: %v", err)
@ -356,8 +329,8 @@ func (c *Client) runRead() {
videoBuf = append(videoBuf, nt.NALU) videoBuf = append(videoBuf, nt.NALU)
} }
} else if c.audioTrack != nil && pair.trackID == c.audioTrack.ID { } else if audioTrack != nil && pair.trackID == audioTrack.ID {
ats, err := c.aacDecoder.Decode(pair.buf) ats, err := aacDecoder.Decode(pair.buf)
if err != nil { if err != nil {
c.log(logger.Warn, "unable to decode audio track: %v", err) c.log(logger.Warn, "unable to decode audio track: %v", err)
continue continue

8
internal/rtmp/aac.go

@ -6,14 +6,6 @@ import (
"github.com/notedit/rtmp/av" "github.com/notedit/rtmp/av"
) )
// WriteAACConfig writes an AAC config.
func (c *Conn) WriteAACConfig(config []byte) error {
return c.WritePacket(av.Packet{
Type: av.AACDecoderConfig,
Data: config,
})
}
// WriteAAC writes an AAC AU. // WriteAAC writes an AAC AU.
func (c *Conn) WriteAAC(au []byte, dts time.Duration) error { func (c *Conn) WriteAAC(au []byte, dts time.Duration) error {
return c.WritePacket(av.Packet{ return c.WritePacket(av.Packet{

22
internal/rtmp/h264.go

@ -4,32 +4,10 @@ import (
"time" "time"
"github.com/notedit/rtmp/av" "github.com/notedit/rtmp/av"
nh264 "github.com/notedit/rtmp/codec/h264"
"github.com/aler9/rtsp-simple-server/internal/h264" "github.com/aler9/rtsp-simple-server/internal/h264"
) )
// WriteH264Config writes a H264 config.
func (c *Conn) WriteH264Config(sps []byte, pps []byte) error {
codec := nh264.Codec{
SPS: map[int][]byte{
0: sps,
},
PPS: map[int][]byte{
0: pps,
},
}
b := make([]byte, 128)
var n int
codec.ToConfig(b, &n)
b = b[:n]
return c.WritePacket(av.Packet{
Type: av.H264DecoderConfig,
Data: b,
})
}
// WriteH264 writes H264 NALUs. // WriteH264 writes H264 NALUs.
func (c *Conn) WriteH264(nalus [][]byte, dts time.Duration) error { func (c *Conn) WriteH264(nalus [][]byte, dts time.Duration) error {
data, err := h264.EncodeAVCC(nalus) data, err := h264.EncodeAVCC(nalus)

58
internal/rtmp/metadata.go

@ -15,12 +15,12 @@ const (
) )
// ReadMetadata extracts track informations from a connection that is publishing. // ReadMetadata extracts track informations from a connection that is publishing.
func (conn *Conn) ReadMetadata() (*gortsplib.Track, *gortsplib.Track, error) { func (c *Conn) ReadMetadata() (*gortsplib.Track, *gortsplib.Track, error) {
var videoTrack *gortsplib.Track var videoTrack *gortsplib.Track
var audioTrack *gortsplib.Track var audioTrack *gortsplib.Track
md, err := func() (flvio.AMFMap, error) { md, err := func() (flvio.AMFMap, error) {
pkt, err := conn.ReadPacket() pkt, err := c.ReadPacket()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -111,7 +111,7 @@ func (conn *Conn) ReadMetadata() (*gortsplib.Track, *gortsplib.Track, error) {
for { for {
var pkt av.Packet var pkt av.Packet
pkt, err = conn.ReadPacket() pkt, err = c.ReadPacket()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -157,8 +157,8 @@ func (conn *Conn) ReadMetadata() (*gortsplib.Track, *gortsplib.Track, error) {
} }
// WriteMetadata writes track informations to a connection that is reading. // WriteMetadata writes track informations to a connection that is reading.
func (conn *Conn) WriteMetadata(videoTrack *gortsplib.Track, audioTrack *gortsplib.Track) error { func (c *Conn) WriteMetadata(videoTrack *gortsplib.Track, audioTrack *gortsplib.Track) error {
return conn.WritePacket(av.Packet{ err := c.WritePacket(av.Packet{
Type: av.Metadata, Type: av.Metadata,
Data: flvio.FillAMF0ValMalloc(flvio.AMFMap{ Data: flvio.FillAMF0ValMalloc(flvio.AMFMap{
{ {
@ -189,4 +189,52 @@ func (conn *Conn) WriteMetadata(videoTrack *gortsplib.Track, audioTrack *gortspl
}, },
}), }),
}) })
if err != nil {
return err
}
if videoTrack != nil {
sps, pps, err := videoTrack.ExtractDataH264()
if err != nil {
return err
}
codec := nh264.Codec{
SPS: map[int][]byte{
0: sps,
},
PPS: map[int][]byte{
0: pps,
},
}
b := make([]byte, 128)
var n int
codec.ToConfig(b, &n)
b = b[:n]
err = c.WritePacket(av.Packet{
Type: av.H264DecoderConfig,
Data: b,
})
if err != nil {
return err
}
}
if audioTrack != nil {
config, err := audioTrack.ExtractDataAAC()
if err != nil {
return err
}
err = c.WritePacket(av.Packet{
Type: av.AACDecoderConfig,
Data: config,
})
if err != nil {
return err
}
}
return nil
} }

Loading…
Cancel
Save