rtmp: improve control message compatibility with non-standard cameras (#4909)
* feat: improve RTMP control message compatibility with non-standard cameras - Add flexible chunk stream ID validation for control messages - Support common non-standard chunk stream IDs (2,3,4,5,6) used by various cameras - Maintain backward compatibility with standard RTMP clients - Fix connection issues with PTZ cameras using chunk stream ID 4 This resolves compatibility issues with IP cameras that don't strictly follow RTMP spec while maintaining full support for standard RTMP implementations. Previously, cameras using non-standard chunk stream IDs would fail with 'unexpected chunk stream ID' errors. Now MediaMTX provides nginx-rtmp level compatibility with real-world camera implementations." * add tests * entirely remove control chunk stream ID validation --------- Co-authored-by: Hyesung.Kim <hyesung.kim@xcath.com> Co-authored-by: aler9 <46489434+aler9@users.noreply.github.com>
This commit is contained in:
co-authored by
Hyesung.Kim
aler9
parent
15e2713ae7
commit
cb16f68432
@@ -12,10 +12,6 @@ type Acknowledge struct {
|
||||
}
|
||||
|
||||
func (m *Acknowledge) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 4 {
|
||||
return fmt.Errorf("unexpected body size")
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@ type SetChunkSize struct {
|
||||
}
|
||||
|
||||
func (m *SetChunkSize) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 4 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -13,10 +13,6 @@ type SetPeerBandwidth struct {
|
||||
}
|
||||
|
||||
func (m *SetPeerBandwidth) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 5 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@ type SetWindowAckSize struct {
|
||||
}
|
||||
|
||||
func (m *SetWindowAckSize) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 4 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@ type UserControlPingRequest struct {
|
||||
}
|
||||
|
||||
func (m *UserControlPingRequest) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 6 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@ type UserControlPingResponse struct {
|
||||
}
|
||||
|
||||
func (m *UserControlPingResponse) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 6 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -13,10 +13,6 @@ type UserControlSetBufferLength struct {
|
||||
}
|
||||
|
||||
func (m *UserControlSetBufferLength) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 10 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@ type UserControlStreamBegin struct {
|
||||
}
|
||||
|
||||
func (m *UserControlStreamBegin) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 6 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@ type UserControlStreamDry struct {
|
||||
}
|
||||
|
||||
func (m *UserControlStreamDry) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 6 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@ type UserControlStreamEOF struct {
|
||||
}
|
||||
|
||||
func (m *UserControlStreamEOF) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 6 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -12,10 +12,6 @@ type UserControlStreamIsRecorded struct {
|
||||
}
|
||||
|
||||
func (m *UserControlStreamIsRecorded) unmarshal(raw *rawmessage.Message) error {
|
||||
if raw.ChunkStreamID != ControlChunkStreamID {
|
||||
return fmt.Errorf("unexpected chunk stream ID")
|
||||
}
|
||||
|
||||
if len(raw.Body) != 6 {
|
||||
return fmt.Errorf("invalid body size")
|
||||
}
|
||||
|
||||
@@ -645,6 +645,22 @@ func TestReader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaderNonStandardControlChunkStreamID(t *testing.T) {
|
||||
buf := []byte{
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||
0x8a, 0xce,
|
||||
}
|
||||
|
||||
bc := bytecounter.NewReader(bytes.NewReader(buf))
|
||||
r := NewReader(bc, bc, nil)
|
||||
dec, err := r.Read()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &UserControlStreamDry{
|
||||
StreamID: 35534,
|
||||
}, dec)
|
||||
}
|
||||
|
||||
func FuzzReader(f *testing.F) {
|
||||
for _, ca := range readWriterCases {
|
||||
f.Add(ca.enc)
|
||||
|
||||
Reference in New Issue
Block a user