Merge pull request #2 from aginetwork7/feature/playback
Skip pyload type not in SDP Add PAUSE API
This commit is contained in:
commit
c0fd928d5e
@ -46,6 +46,7 @@ const (
|
||||
DESCRIBE = "DESCRIBE"
|
||||
OPTIONS = "OPTIONS"
|
||||
PLAY = "PLAY"
|
||||
PAUSE = "PAUSE"
|
||||
SETUP = "SETUP"
|
||||
TEARDOWN = "TEARDOWN"
|
||||
)
|
||||
@ -96,6 +97,7 @@ type RTSPClient struct {
|
||||
sequenceNumber int
|
||||
end int
|
||||
offset int
|
||||
status string
|
||||
}
|
||||
|
||||
type RTSPClientOptions struct {
|
||||
@ -271,7 +273,7 @@ func (client *RTSPClient) startStream() {
|
||||
client.Println("RTSP Client RTP SetDeadline", err)
|
||||
return
|
||||
}
|
||||
if int(time.Now().Sub(timer).Seconds()) > 25 {
|
||||
if int(time.Since(timer).Seconds()) > 25 {
|
||||
err := client.request(OPTIONS, map[string]string{"Require": "implicit-play"}, client.control, false, true)
|
||||
if err != nil {
|
||||
client.Println("RTSP Client RTP keep-alive", err)
|
||||
@ -279,6 +281,10 @@ func (client *RTSPClient) startStream() {
|
||||
}
|
||||
timer = time.Now()
|
||||
}
|
||||
if client.status == PAUSE {
|
||||
// client.Println("RTSP Client PAUSE")
|
||||
continue
|
||||
}
|
||||
if !fixed {
|
||||
nb, err := io.ReadFull(client.connRW, header)
|
||||
if err != nil || nb != 4 {
|
||||
@ -335,7 +341,7 @@ func (client *RTSPClient) startStream() {
|
||||
return
|
||||
}
|
||||
responseTmp = append(responseTmp, oneb...)
|
||||
if (len(responseTmp) > 4 && bytes.Compare(responseTmp[len(responseTmp)-4:], []byte("\r\n\r\n")) == 0) || len(responseTmp) > 768 {
|
||||
if (len(responseTmp) > 4 && bytes.Equal(responseTmp[len(responseTmp)-4:], []byte("\r\n\r\n"))) || len(responseTmp) > 768 {
|
||||
if strings.Contains(string(responseTmp), "Content-Length:") {
|
||||
si, err := strconv.Atoi(stringInBetween(string(responseTmp), "Content-Length: ", "\r\n"))
|
||||
if err != nil {
|
||||
@ -371,15 +377,13 @@ func (client *RTSPClient) request(method string, customHeaders map[string]string
|
||||
if client.clientDigest {
|
||||
builder.WriteString(fmt.Sprintf("Authorization: %s\r\n", client.createDigest(method, uri)))
|
||||
}
|
||||
if customHeaders != nil {
|
||||
for k, v := range customHeaders {
|
||||
builder.WriteString(fmt.Sprintf("%s: %s\r\n", k, v))
|
||||
}
|
||||
for k, v := range customHeaders {
|
||||
builder.WriteString(fmt.Sprintf("%s: %s\r\n", k, v))
|
||||
}
|
||||
for k, v := range client.headers {
|
||||
builder.WriteString(fmt.Sprintf("%s: %s\r\n", k, v))
|
||||
}
|
||||
builder.WriteString(fmt.Sprintf("\r\n"))
|
||||
builder.WriteString("\r\n")
|
||||
client.Println(builder.String())
|
||||
s := builder.String()
|
||||
_, err = client.connRW.WriteString(s)
|
||||
@ -505,6 +509,31 @@ func (client *RTSPClient) request(method string, customHeaders map[string]string
|
||||
return
|
||||
}
|
||||
|
||||
func (client *RTSPClient) Pause() error {
|
||||
if err := client.request(PAUSE, nil, client.pURL.String(), false, true); err != nil {
|
||||
return err
|
||||
}
|
||||
client.status = PAUSE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *RTSPClient) Play(customHeaders map[string]string) error {
|
||||
if err := client.request(PLAY, customHeaders, client.pURL.String(), false, true); err != nil {
|
||||
return err
|
||||
}
|
||||
client.status = PLAY
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *RTSPClient) Seek(customHeaders map[string]string, target int64) error {
|
||||
customHeaders["Range"] = fmt.Sprintf("npt=%d.00-", target)
|
||||
if err := client.request(PLAY, customHeaders, client.pURL.String(), false, true); err != nil {
|
||||
return err
|
||||
}
|
||||
client.status = PLAY
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *RTSPClient) Close() {
|
||||
if client.conn != nil {
|
||||
client.conn.SetDeadline(time.Now().Add(time.Second))
|
||||
@ -561,7 +590,7 @@ func (client *RTSPClient) CodecUpdateSPS(val []byte) {
|
||||
if client.videoCodec != av.H264 && client.videoCodec != av.H265 {
|
||||
return
|
||||
}
|
||||
if bytes.Compare(val, client.sps) == 0 {
|
||||
if bytes.Equal(val, client.sps) {
|
||||
return
|
||||
}
|
||||
client.sps = val
|
||||
@ -601,7 +630,7 @@ func (client *RTSPClient) CodecUpdatePPS(val []byte) {
|
||||
if client.videoCodec != av.H264 && client.videoCodec != av.H265 {
|
||||
return
|
||||
}
|
||||
if bytes.Compare(val, client.pps) == 0 {
|
||||
if bytes.Equal(val, client.pps) {
|
||||
return
|
||||
}
|
||||
client.pps = val
|
||||
@ -641,7 +670,7 @@ func (client *RTSPClient) CodecUpdateVPS(val []byte) {
|
||||
if client.videoCodec != av.H265 {
|
||||
return
|
||||
}
|
||||
if bytes.Compare(val, client.vps) == 0 {
|
||||
if bytes.Equal(val, client.vps) {
|
||||
return
|
||||
}
|
||||
client.vps = val
|
||||
|
@ -2,12 +2,14 @@ package rtspv2
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/deepch/vdk/av"
|
||||
"github.com/deepch/vdk/codec/aacparser"
|
||||
"github.com/deepch/vdk/codec/h264parser"
|
||||
"github.com/deepch/vdk/codec/h265parser"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -15,22 +17,40 @@ const (
|
||||
TimeDelay = 1
|
||||
)
|
||||
|
||||
func (client *RTSPClient) containsPayloadType(pt int) bool {
|
||||
var exist bool
|
||||
for _, sdp := range client.mediaSDP {
|
||||
if sdp.Rtpmap == pt {
|
||||
exist = true
|
||||
}
|
||||
}
|
||||
return exist
|
||||
}
|
||||
|
||||
func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) {
|
||||
content := *payloadRAW
|
||||
firstByte := content[4]
|
||||
padding := (firstByte>>5)&1 == 1
|
||||
extension := (firstByte>>4)&1 == 1
|
||||
CSRCCnt := int(firstByte & 0x0f)
|
||||
client.sequenceNumber = int(binary.BigEndian.Uint16(content[6:8]))
|
||||
client.timestamp = int64(binary.BigEndian.Uint32(content[8:16]))
|
||||
|
||||
payloadType := int(content[5] & 0x7f)
|
||||
sequenceNumber := int(binary.BigEndian.Uint16(content[6:8]))
|
||||
timestamp := int64(binary.BigEndian.Uint32(content[8:12]))
|
||||
if isRTCPPacket(content) {
|
||||
client.Println("skipping RTCP packet")
|
||||
return nil, false
|
||||
}
|
||||
|
||||
client.offset = RTPHeaderSize
|
||||
if !client.containsPayloadType(payloadType) {
|
||||
client.Println(fmt.Sprintf("skipping RTP packet, paytload type: %v", payloadType))
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// client.Println(fmt.Sprintf("padding: %v, extension: %v, csrccnt: %d, sequence number: %d.payload type: %d, timestamp: %d",
|
||||
// padding, extension, CSRCCnt, sequenceNumber, payloadType, timestamp))
|
||||
client.offset = RTPHeaderSize
|
||||
client.sequenceNumber = sequenceNumber
|
||||
client.timestamp = timestamp
|
||||
client.end = len(content)
|
||||
if client.end-client.offset >= 4*CSRCCnt {
|
||||
client.offset += 4 * CSRCCnt
|
||||
@ -88,6 +108,7 @@ func (client *RTSPClient) handleVideo(content []byte) ([]*av.Packet, bool) {
|
||||
}
|
||||
nalRaw, _ := h264parser.SplitNALUs(content[client.offset:client.end])
|
||||
if len(nalRaw) == 0 || len(nalRaw[0]) == 0 {
|
||||
client.Println("nal Raw 0", nalRaw)
|
||||
return nil, false
|
||||
}
|
||||
var retmap []*av.Packet
|
||||
|
Loading…
Reference in New Issue
Block a user