Merge pull request #2 from aginetwork7/feature/playback

Skip pyload type not in SDP
Add PAUSE API
This commit is contained in:
dashuang 2024-03-18 12:51:12 +08:00 committed by GitHub
commit c0fd928d5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 66 additions and 16 deletions

View File

@ -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 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

View File

@ -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