mirror of https://bitbucket.org/ausocean/av.git
revid: fixed rtpPort and rtcpPort parsing and added H264 and H265 IDs
Added H264ID and H265ID consts and added logic to select this const for use in encoder based on mediaType param in NewEncoder. Also now declaring PMT in NewEncoder so that we can set streamID correctly based on mediaType.
This commit is contained in:
parent
bd56e936a4
commit
548b7caa81
|
@ -55,30 +55,6 @@ var (
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// standardPmt is a minimal PMT, without descriptors for time and location.
|
|
||||||
standardPmt = psi.PSI{
|
|
||||||
Pf: 0x00,
|
|
||||||
Tid: 0x02,
|
|
||||||
Ssi: true,
|
|
||||||
Sl: 0x12,
|
|
||||||
Tss: &psi.TSS{
|
|
||||||
Tide: 0x01,
|
|
||||||
V: 0,
|
|
||||||
Cni: true,
|
|
||||||
Sn: 0,
|
|
||||||
Lsn: 0,
|
|
||||||
Sd: &psi.PMT{
|
|
||||||
Pcrpid: 0x0100,
|
|
||||||
Pil: 0,
|
|
||||||
Essd: &psi.ESSD{
|
|
||||||
St: 0x1b,
|
|
||||||
Epid: 0x0100,
|
|
||||||
Esil: 0x00,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -94,7 +70,7 @@ var Meta *meta.Data
|
||||||
|
|
||||||
var (
|
var (
|
||||||
patTable = standardPat.Bytes()
|
patTable = standardPat.Bytes()
|
||||||
pmtTable = standardPmt.Bytes()
|
pmtTable []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -103,14 +79,16 @@ const (
|
||||||
pmtPid = 4096
|
pmtPid = 4096
|
||||||
videoPid = 256
|
videoPid = 256
|
||||||
audioPid = 210
|
audioPid = 210
|
||||||
videoStreamID = 0xe0 // First video stream ID.
|
H264ID = 27
|
||||||
|
H265ID = 36
|
||||||
audioStreamID = 0xc0 // First audio stream ID.
|
audioStreamID = 0xc0 // First audio stream ID.
|
||||||
)
|
)
|
||||||
|
|
||||||
// Video and Audio constants are used to communicate which media type will be encoded when creating a
|
// Video and Audio constants are used to communicate which media type will be encoded when creating a
|
||||||
// new encoder with NewEncoder.
|
// new encoder with NewEncoder.
|
||||||
const (
|
const (
|
||||||
Video = iota
|
H264 = iota
|
||||||
|
H265
|
||||||
Audio
|
Audio
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -158,11 +136,38 @@ func NewEncoder(dst io.WriteCloser, rate float64, mediaType int) *Encoder {
|
||||||
case Audio:
|
case Audio:
|
||||||
mPid = audioPid
|
mPid = audioPid
|
||||||
sid = audioStreamID
|
sid = audioStreamID
|
||||||
case Video:
|
case H265:
|
||||||
mPid = videoPid
|
mPid = videoPid
|
||||||
sid = videoStreamID
|
sid = H264ID
|
||||||
|
case H264:
|
||||||
|
mPid = videoPid
|
||||||
|
sid = H265ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// standardPmt is a minimal PMT, without descriptors for time and location.
|
||||||
|
pmtTable = (&psi.PSI{
|
||||||
|
Pf: 0x00,
|
||||||
|
Tid: 0x02,
|
||||||
|
Ssi: true,
|
||||||
|
Sl: 0x12,
|
||||||
|
Tss: &psi.TSS{
|
||||||
|
Tide: 0x01,
|
||||||
|
V: 0,
|
||||||
|
Cni: true,
|
||||||
|
Sn: 0,
|
||||||
|
Lsn: 0,
|
||||||
|
Sd: &psi.PMT{
|
||||||
|
Pcrpid: 0x0100,
|
||||||
|
Pil: 0,
|
||||||
|
Essd: &psi.ESSD{
|
||||||
|
St: byte(sid),
|
||||||
|
Epid: 0x0100,
|
||||||
|
Esil: 0x00,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).Bytes()
|
||||||
|
|
||||||
return &Encoder{
|
return &Encoder{
|
||||||
dst: dst,
|
dst: dst,
|
||||||
|
|
||||||
|
@ -219,7 +224,7 @@ func (e *Encoder) Write(data []byte) (int, error) {
|
||||||
|
|
||||||
// Prepare PES data.
|
// Prepare PES data.
|
||||||
pesPkt := pes.Packet{
|
pesPkt := pes.Packet{
|
||||||
StreamID: e.streamID,
|
StreamID: byte(36),
|
||||||
PDI: hasPTS,
|
PDI: hasPTS,
|
||||||
PTS: e.pts(),
|
PTS: e.pts(),
|
||||||
Data: data,
|
Data: data,
|
||||||
|
|
|
@ -99,7 +99,7 @@ func TestEncodeVideo(t *testing.T) {
|
||||||
|
|
||||||
// Create the dst and write the test data to encoder.
|
// Create the dst and write the test data to encoder.
|
||||||
dst := &destination{}
|
dst := &destination{}
|
||||||
_, err := NewEncoder(nopCloser{dst}, 25, Video).Write(data)
|
_, err := NewEncoder(nopCloser{dst}, 25, H264).Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not write data to encoder, failed with err: %v\n", err)
|
t.Fatalf("could not write data to encoder, failed with err: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ const fps = 25
|
||||||
func TestMetaEncode1(t *testing.T) {
|
func TestMetaEncode1(t *testing.T) {
|
||||||
Meta = meta.New()
|
Meta = meta.New()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
e := NewEncoder(nopCloser{&buf}, fps, Video)
|
e := NewEncoder(nopCloser{&buf}, fps, H264)
|
||||||
Meta.Add("ts", "12345678")
|
Meta.Add("ts", "12345678")
|
||||||
if err := e.writePSI(); err != nil {
|
if err := e.writePSI(); err != nil {
|
||||||
t.Errorf(errUnexpectedErr, err.Error())
|
t.Errorf(errUnexpectedErr, err.Error())
|
||||||
|
@ -76,7 +76,7 @@ func TestMetaEncode1(t *testing.T) {
|
||||||
func TestMetaEncode2(t *testing.T) {
|
func TestMetaEncode2(t *testing.T) {
|
||||||
Meta = meta.New()
|
Meta = meta.New()
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
e := NewEncoder(nopCloser{&buf}, fps, Video)
|
e := NewEncoder(nopCloser{&buf}, fps, H264)
|
||||||
Meta.Add("ts", "12345678")
|
Meta.Add("ts", "12345678")
|
||||||
Meta.Add("loc", "1234,4321,1234")
|
Meta.Add("loc", "1234,4321,1234")
|
||||||
if err := e.writePSI(); err != nil {
|
if err := e.writePSI(); err != nil {
|
||||||
|
|
|
@ -126,7 +126,7 @@ func writePSI(b *bytes.Buffer) error {
|
||||||
func writeFrame(b *bytes.Buffer, frame []byte, pts uint64) error {
|
func writeFrame(b *bytes.Buffer, frame []byte, pts uint64) error {
|
||||||
// Prepare PES data.
|
// Prepare PES data.
|
||||||
pesPkt := pes.Packet{
|
pesPkt := pes.Packet{
|
||||||
StreamID: videoStreamID,
|
StreamID: H264ID,
|
||||||
PDI: hasPTS,
|
PDI: hasPTS,
|
||||||
PTS: pts,
|
PTS: pts,
|
||||||
Data: frame,
|
Data: frame,
|
||||||
|
|
|
@ -166,7 +166,14 @@ func (r *Revid) reset(config Config) error {
|
||||||
|
|
||||||
err = r.setupPipeline(
|
err = r.setupPipeline(
|
||||||
func(dst io.WriteCloser, fps int) (io.WriteCloser, error) {
|
func(dst io.WriteCloser, fps int) (io.WriteCloser, error) {
|
||||||
e := mts.NewEncoder(dst, float64(fps), mts.Video)
|
var st int
|
||||||
|
switch r.config.Input {
|
||||||
|
case Raspivid, File, V4L:
|
||||||
|
st = mts.H264
|
||||||
|
case RTSPCamera:
|
||||||
|
st = mts.H265
|
||||||
|
}
|
||||||
|
e := mts.NewEncoder(dst, float64(fps), st)
|
||||||
return e, nil
|
return e, nil
|
||||||
},
|
},
|
||||||
func(dst io.WriteCloser, fps int) (io.WriteCloser, error) {
|
func(dst io.WriteCloser, fps int) (io.WriteCloser, error) {
|
||||||
|
@ -607,6 +614,7 @@ func (r *Revid) setupInputForFile() (func() error, error) {
|
||||||
|
|
||||||
func (r *Revid) startRTSPCamera() (func() error, error) {
|
func (r *Revid) startRTSPCamera() (func() error, error) {
|
||||||
rtspClt, err := rtsp.NewClient(r.config.RTSPURL)
|
rtspClt, err := rtsp.NewClient(r.config.RTSPURL)
|
||||||
|
fmt.Printf("RTSPURL: %v\n", r.config.RTSPURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -623,12 +631,12 @@ func (r *Revid) startRTSPCamera() (func() error, error) {
|
||||||
}
|
}
|
||||||
r.config.Logger.Log(logger.Info, pkg+"RTSP server DESCRIBE response", "response", resp.String())
|
r.config.Logger.Log(logger.Info, pkg+"RTSP server DESCRIBE response", "response", resp.String())
|
||||||
|
|
||||||
rtpPort, err := strconv.Atoi(strings.Split(r.config.RTPRecvAddr, ":")[0])
|
rtpPort, err := strconv.Atoi(strings.Split(r.config.RTPRecvAddr, ":")[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rtcpPort, err := strconv.Atoi(strings.Split(r.config.RTCPAddr, ":")[0])
|
rtcpPort, err := strconv.Atoi(strings.Split(r.config.RTCPAddr, ":")[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -644,6 +652,7 @@ func (r *Revid) startRTSPCamera() (func() error, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
r.config.Logger.Log(logger.Info, pkg+"RTSP server PLAY response", "response", resp.String())
|
||||||
|
|
||||||
// TODO(saxon): use rtcp client to maintain rtp stream.
|
// TODO(saxon): use rtcp client to maintain rtp stream.
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ func TestMtsSenderSegment(t *testing.T) {
|
||||||
const numberOfClips = 11
|
const numberOfClips = 11
|
||||||
dst := &destination{t: t, done: make(chan struct{}), doneAt: numberOfClips}
|
dst := &destination{t: t, done: make(chan struct{}), doneAt: numberOfClips}
|
||||||
sender := newMtsSender(dst, (*dummyLogger)(t).log, rbSize, rbElementSize, 0)
|
sender := newMtsSender(dst, (*dummyLogger)(t).log, rbSize, rbElementSize, 0)
|
||||||
encoder := mts.NewEncoder(sender, 25, mts.Video)
|
encoder := mts.NewEncoder(sender, 25, mts.H264)
|
||||||
|
|
||||||
// Turn time based PSI writing off for encoder.
|
// Turn time based PSI writing off for encoder.
|
||||||
const psiSendCount = 10
|
const psiSendCount = 10
|
||||||
|
@ -212,7 +212,7 @@ func TestMtsSenderFailedSend(t *testing.T) {
|
||||||
const clipToFailAt = 3
|
const clipToFailAt = 3
|
||||||
dst := &destination{t: t, testFails: true, failAt: clipToFailAt, done: make(chan struct{})}
|
dst := &destination{t: t, testFails: true, failAt: clipToFailAt, done: make(chan struct{})}
|
||||||
sender := newMtsSender(dst, (*dummyLogger)(t).log, rbSize, rbElementSize, 0)
|
sender := newMtsSender(dst, (*dummyLogger)(t).log, rbSize, rbElementSize, 0)
|
||||||
encoder := mts.NewEncoder(sender, 25, mts.Video)
|
encoder := mts.NewEncoder(sender, 25, mts.H264)
|
||||||
|
|
||||||
// Turn time based PSI writing off for encoder and send PSI every 10 packets.
|
// Turn time based PSI writing off for encoder and send PSI every 10 packets.
|
||||||
const psiSendCount = 10
|
const psiSendCount = 10
|
||||||
|
@ -292,7 +292,7 @@ func TestMtsSenderDiscontinuity(t *testing.T) {
|
||||||
const clipToDelay = 3
|
const clipToDelay = 3
|
||||||
dst := &destination{t: t, sendDelay: 10 * time.Millisecond, delayAt: clipToDelay, done: make(chan struct{})}
|
dst := &destination{t: t, sendDelay: 10 * time.Millisecond, delayAt: clipToDelay, done: make(chan struct{})}
|
||||||
sender := newMtsSender(dst, (*dummyLogger)(t).log, 1, rbElementSize, 0)
|
sender := newMtsSender(dst, (*dummyLogger)(t).log, 1, rbElementSize, 0)
|
||||||
encoder := mts.NewEncoder(sender, 25, mts.Video)
|
encoder := mts.NewEncoder(sender, 25, mts.H264)
|
||||||
|
|
||||||
// Turn time based PSI writing off for encoder.
|
// Turn time based PSI writing off for encoder.
|
||||||
const psiSendCount = 10
|
const psiSendCount = 10
|
||||||
|
|
Loading…
Reference in New Issue