mirror of
https://github.com/datarhei/core.git
synced 2025-09-27 04:16:25 +08:00
Add alternative streamid format for SRT
The streamid format that starts with #!: is recommended in the SRT specs but it usually causes trouble where you're limited in the use of such characters. Some hardware devices will not accept such streamids. The alternative format is simpler and has the form [resource](,token:[token])?(,mode:[mode])? token and mode are optional. mode can have the values "publish" or "request". If mode is not provided, a value of "request" is assumed.
This commit is contained in:
58
srt/srt.go
58
srt/srt.go
@@ -5,6 +5,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -365,6 +366,59 @@ type streamInfo struct {
|
|||||||
func parseStreamId(streamid string) (streamInfo, error) {
|
func parseStreamId(streamid string) (streamInfo, error) {
|
||||||
si := streamInfo{}
|
si := streamInfo{}
|
||||||
|
|
||||||
|
if strings.HasPrefix(streamid, "#!:") {
|
||||||
|
return parseOldStreamId(streamid)
|
||||||
|
}
|
||||||
|
|
||||||
|
re := regexp.MustCompile(`,(token|mode):(.+)`)
|
||||||
|
|
||||||
|
results := map[string]string{}
|
||||||
|
|
||||||
|
idEnd := -1
|
||||||
|
value := streamid
|
||||||
|
key := ""
|
||||||
|
|
||||||
|
for {
|
||||||
|
matches := re.FindStringSubmatchIndex(value)
|
||||||
|
if matches == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if idEnd < 0 {
|
||||||
|
idEnd = matches[2] - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(key) != 0 {
|
||||||
|
results[key] = value[:matches[2]-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
key = value[matches[2]:matches[3]]
|
||||||
|
value = value[matches[4]:matches[5]]
|
||||||
|
|
||||||
|
results[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
if idEnd < 0 {
|
||||||
|
idEnd = len(streamid)
|
||||||
|
}
|
||||||
|
|
||||||
|
si.resource = streamid[:idEnd]
|
||||||
|
if token, ok := results["token"]; ok {
|
||||||
|
si.token = token
|
||||||
|
}
|
||||||
|
|
||||||
|
if mode, ok := results["mode"]; ok {
|
||||||
|
si.mode = mode
|
||||||
|
} else {
|
||||||
|
si.mode = "request"
|
||||||
|
}
|
||||||
|
|
||||||
|
return si, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseOldStreamId(streamid string) (streamInfo, error) {
|
||||||
|
si := streamInfo{}
|
||||||
|
|
||||||
if !strings.HasPrefix(streamid, "#!:") {
|
if !strings.HasPrefix(streamid, "#!:") {
|
||||||
return si, fmt.Errorf("unknown streamid format")
|
return si, fmt.Errorf("unknown streamid format")
|
||||||
}
|
}
|
||||||
@@ -373,7 +427,7 @@ func parseStreamId(streamid string) (streamInfo, error) {
|
|||||||
|
|
||||||
kvs := strings.Split(streamid, ",")
|
kvs := strings.Split(streamid, ",")
|
||||||
|
|
||||||
split := func(s, sep string) (string, string, error) {
|
splitFn := func(s, sep string) (string, string, error) {
|
||||||
splitted := strings.SplitN(s, sep, 2)
|
splitted := strings.SplitN(s, sep, 2)
|
||||||
|
|
||||||
if len(splitted) != 2 {
|
if len(splitted) != 2 {
|
||||||
@@ -384,7 +438,7 @@ func parseStreamId(streamid string) (streamInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, kv := range kvs {
|
for _, kv := range kvs {
|
||||||
key, value, err := split(kv, "=")
|
key, value, err := splitFn(kv, "=")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,25 @@ import (
|
|||||||
|
|
||||||
func TestParseStreamId(t *testing.T) {
|
func TestParseStreamId(t *testing.T) {
|
||||||
streamids := map[string]streamInfo{
|
streamids := map[string]streamInfo{
|
||||||
"bla": {},
|
"bla": {resource: "bla", mode: "request"},
|
||||||
|
"bla,mode:publish": {resource: "bla", mode: "publish"},
|
||||||
|
"123456789": {resource: "123456789", mode: "request"},
|
||||||
|
"bla,token:foobar": {resource: "bla", token: "foobar", mode: "request"},
|
||||||
|
"bla,token:foo,bar": {resource: "bla", token: "foo,bar", mode: "request"},
|
||||||
|
"123456789,mode:publish,token:foobar": {resource: "123456789", token: "foobar", mode: "publish"},
|
||||||
|
"mode:publish": {resource: "mode:publish", mode: "request"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for streamid, wantsi := range streamids {
|
||||||
|
si, err := parseStreamId(streamid)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, wantsi, si)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseOldStreamId(t *testing.T) {
|
||||||
|
streamids := map[string]streamInfo{
|
||||||
"#!:": {},
|
"#!:": {},
|
||||||
"#!:key=value": {},
|
"#!:key=value": {},
|
||||||
"#!:m=publish": {mode: "publish"},
|
"#!:m=publish": {mode: "publish"},
|
||||||
@@ -19,7 +37,7 @@ func TestParseStreamId(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for streamid, wantsi := range streamids {
|
for streamid, wantsi := range streamids {
|
||||||
si, _ := parseStreamId(streamid)
|
si, _ := parseOldStreamId(streamid)
|
||||||
|
|
||||||
require.Equal(t, wantsi, si)
|
require.Equal(t, wantsi, si)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user