Merge branch 'fix/issue-2-configurable-map' into m2-webrtc-core-integration
This commit is contained in:
commit
73d4049893
5 changed files with 104 additions and 10 deletions
|
|
@ -32,7 +32,16 @@ func BuildArgs(cfg appcfg.ConfigWebRTC, videoPort int) []string {
|
|||
acopy = []string{"-c:a", "libopus", "-b:a", "96k"}
|
||||
}
|
||||
|
||||
args := []string{"-map", "0:v:0"}
|
||||
videoMap := cfg.VideoMap
|
||||
if videoMap == "" {
|
||||
videoMap = "0:v:0"
|
||||
}
|
||||
audioMap := cfg.AudioMap
|
||||
if audioMap == "" {
|
||||
audioMap = "0:a:0"
|
||||
}
|
||||
|
||||
args := []string{"-map", videoMap}
|
||||
args = append(args, vcopy...)
|
||||
args = append(args,
|
||||
"-payload_type", fmt.Sprint(cfg.VideoPT),
|
||||
|
|
@ -40,7 +49,7 @@ func BuildArgs(cfg appcfg.ConfigWebRTC, videoPort int) []string {
|
|||
fmt.Sprintf("udp://127.0.0.1:%d?pkt_size=1316", videoPort),
|
||||
)
|
||||
|
||||
args = append(args, "-map", "0:a:0")
|
||||
args = append(args, "-map", audioMap)
|
||||
args = append(args, acopy...)
|
||||
args = append(args,
|
||||
"-payload_type", fmt.Sprint(cfg.AudioPT),
|
||||
|
|
|
|||
|
|
@ -87,3 +87,46 @@ func any(haystack []string, prefix string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TestBuildArgs_DefaultMaps confirms 0:v:0 / 0:a:0 are emitted when
|
||||
// VideoMap / AudioMap are empty (regression on the fix for issue #2 —
|
||||
// the prior version had these as hardcoded literals; if VideoMap is
|
||||
// ever empty unexpectedly, BuildArgs must still produce a working
|
||||
// command line).
|
||||
func TestBuildArgs_DefaultMaps(t *testing.T) {
|
||||
cfg := appcfg.ConfigWebRTC{Enabled: true, VideoPT: 102, AudioPT: 111}
|
||||
got := BuildArgs(cfg, 50000)
|
||||
if !contains(got, "-map", "0:v:0") {
|
||||
t.Fatalf("expected default video map 0:v:0, got %v", got)
|
||||
}
|
||||
if !contains(got, "-map", "0:a:0") {
|
||||
t.Fatalf("expected default audio map 0:a:0, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestBuildArgs_CustomMaps drives the issue-#2 fix: when the user
|
||||
// configures a multi-input pipeline (audio on input #1, etc.), the
|
||||
// emitted -map values must follow the user's choice rather than the
|
||||
// "0:v:0"/"0:a:0" assumption.
|
||||
func TestBuildArgs_CustomMaps(t *testing.T) {
|
||||
cfg := appcfg.ConfigWebRTC{
|
||||
Enabled: true,
|
||||
VideoPT: 102,
|
||||
AudioPT: 111,
|
||||
VideoMap: "0:v:1",
|
||||
AudioMap: "1:a:0",
|
||||
}
|
||||
got := BuildArgs(cfg, 50000)
|
||||
if !contains(got, "-map", "0:v:1") {
|
||||
t.Fatalf("expected custom video map 0:v:1, got %v", got)
|
||||
}
|
||||
if !contains(got, "-map", "1:a:0") {
|
||||
t.Fatalf("expected custom audio map 1:a:0, got %v", got)
|
||||
}
|
||||
// The default literals should NOT appear when overridden.
|
||||
for _, opt := range got {
|
||||
if opt == "0:v:0" || opt == "0:a:0" {
|
||||
t.Errorf("expected no default maps in output, found %q in %v", opt, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,10 +44,12 @@ type ProcessConfigLimits struct {
|
|||
|
||||
// ProcessConfig represents the configuration of an ffmpeg process
|
||||
type ProcessConfigWebRTC struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
VideoPT uint8 `json:"video_pt,omitempty"`
|
||||
AudioPT uint8 `json:"audio_pt,omitempty"`
|
||||
ForceTranscode bool `json:"force_transcode,omitempty"`
|
||||
Enabled bool `json:"enabled"`
|
||||
VideoPT uint8 `json:"video_pt,omitempty"`
|
||||
AudioPT uint8 `json:"audio_pt,omitempty"`
|
||||
ForceTranscode bool `json:"force_transcode,omitempty"`
|
||||
VideoMap string `json:"video_map,omitempty"`
|
||||
AudioMap string `json:"audio_map,omitempty"`
|
||||
}
|
||||
|
||||
type ProcessConfig struct {
|
||||
|
|
@ -83,6 +85,8 @@ func (cfg *ProcessConfig) Marshal() *app.Config {
|
|||
VideoPT: cfg.WebRTC.VideoPT,
|
||||
AudioPT: cfg.WebRTC.AudioPT,
|
||||
ForceTranscode: cfg.WebRTC.ForceTranscode,
|
||||
VideoMap: cfg.WebRTC.VideoMap,
|
||||
AudioMap: cfg.WebRTC.AudioMap,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -168,6 +172,8 @@ func (cfg *ProcessConfig) Unmarshal(c *app.Config) {
|
|||
cfg.WebRTC.VideoPT = c.WebRTC.VideoPT
|
||||
cfg.WebRTC.AudioPT = c.WebRTC.AudioPT
|
||||
cfg.WebRTC.ForceTranscode = c.WebRTC.ForceTranscode
|
||||
cfg.WebRTC.VideoMap = c.WebRTC.VideoMap
|
||||
cfg.WebRTC.AudioMap = c.WebRTC.AudioMap
|
||||
|
||||
cfg.Options = make([]string, len(c.Options))
|
||||
copy(cfg.Options, c.Options)
|
||||
|
|
|
|||
|
|
@ -79,3 +79,31 @@ func TestProcessConfigWebRTCDefaults(t *testing.T) {
|
|||
t.Fatalf("default should be disabled, got %+v", cfg.WebRTC)
|
||||
}
|
||||
}
|
||||
|
||||
// TestProcessConfigWebRTCMapsRoundtrip extends the WebRTC DTO
|
||||
// roundtrip with the issue-#2 VideoMap/AudioMap fields so the
|
||||
// regression doesn't repeat: a multi-input pipeline that sets
|
||||
// `audio_map: "1:a:0"` must reach the restream config layer
|
||||
// unchanged.
|
||||
func TestProcessConfigWebRTCMapsRoundtrip(t *testing.T) {
|
||||
body := []byte(`{
|
||||
"id":"p","input":[{"id":"i","address":"x"}],"output":[{"id":"o","address":"-"}],
|
||||
"webrtc":{"enabled":true,"video_map":"0:v:1","audio_map":"1:a:0"}
|
||||
}`)
|
||||
var dto ProcessConfig
|
||||
if err := json.Unmarshal(body, &dto); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if dto.WebRTC.VideoMap != "0:v:1" || dto.WebRTC.AudioMap != "1:a:0" {
|
||||
t.Fatalf("DTO maps lost: %+v", dto.WebRTC)
|
||||
}
|
||||
cfg := dto.Marshal()
|
||||
if cfg.WebRTC.VideoMap != "0:v:1" || cfg.WebRTC.AudioMap != "1:a:0" {
|
||||
t.Fatalf("app.Config maps lost: %+v", cfg.WebRTC)
|
||||
}
|
||||
var back ProcessConfig
|
||||
back.Unmarshal(cfg)
|
||||
if back.WebRTC.VideoMap != "0:v:1" || back.WebRTC.AudioMap != "1:a:0" {
|
||||
t.Fatalf("Unmarshal lost maps: %+v", back.WebRTC)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,10 +25,18 @@ type ConfigIO struct {
|
|||
// RTP to a loopback UDP port the subsystem allocates. The subsystem reads
|
||||
// that RTP and fans it out to WHEP subscribers.
|
||||
type ConfigWebRTC struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
VideoPT uint8 `json:"video_pt"`
|
||||
AudioPT uint8 `json:"audio_pt"`
|
||||
ForceTranscode bool `json:"force_transcode"`
|
||||
Enabled bool `json:"enabled"`
|
||||
VideoPT uint8 `json:"video_pt"`
|
||||
AudioPT uint8 `json:"audio_pt"`
|
||||
ForceTranscode bool `json:"force_transcode"`
|
||||
|
||||
// VideoMap / AudioMap select which input stream the WebRTC RTP
|
||||
// legs draw from. Defaults are "0:v:0" and "0:a:0" — correct for
|
||||
// any RTMP / SRT publisher (single input, both A and V on input
|
||||
// 0). For multi-input pipelines (lavfi test sources, SDI capture
|
||||
// fed alongside file audio, etc.) the operator can override.
|
||||
VideoMap string `json:"video_map,omitempty"`
|
||||
AudioMap string `json:"audio_map,omitempty"`
|
||||
}
|
||||
|
||||
// Clone returns a deep copy of the WebRTC config (currently a value copy;
|
||||
|
|
|
|||
Loading…
Reference in a new issue