diff --git a/input/gvctrl/gvctrl.go b/input/gvctrl/gvctrl.go index 7d42102e..5a60f6c3 100644 --- a/input/gvctrl/gvctrl.go +++ b/input/gvctrl/gvctrl.go @@ -59,34 +59,37 @@ const ( ) const ( - defaultCodec = codecH264 - defaultRes = "6400360" // 360p - defaultFrameRate = "25000" // 25 fps - defaultVBR = "0" // Variable bitrate off - defaultQuality = qualityGood - defaultBitRate = "512000" // 512 kbps (lowest with 360p) - defaultRefresh = "2000" // 2 seconds + defaultCodec = codecH264 + defaultRes = "6400360" // 360p + defaultFrameRate = "25000" // 25 fps + defaultVBR = "0" // Variable bitrate off + defaultQuality = qualityGood + defaultVBRBitRate = "250000" // 512 kbps (lowest with 360p) + defaultCBRBitRate = "512000" + defaultRefresh = "2000" // 2 seconds ) type settings struct { - codec codec - res string - frameRate string - vbr string - quality quality - bitRate string - refresh string + codec codec + res string + frameRate string + vbr string + quality quality + vbrBitRate string + cbrBitRate string + refresh string } func newSettings() settings { return settings{ - codec: defaultCodec, - res: defaultRes, - frameRate: defaultFrameRate, - vbr: defaultVBR, - quality: defaultQuality, - bitRate: defaultBitRate, - refresh: defaultRefresh, + codec: defaultCodec, + res: defaultRes, + frameRate: defaultFrameRate, + vbr: defaultVBR, + quality: defaultQuality, + vbrBitRate: defaultVBRBitRate, + cbrBitRate: defaultCBRBitRate, + refresh: defaultRefresh, } } @@ -184,7 +187,7 @@ func VariableBitRate(b bool) option { } } -func Quality(q quality) option { +func VBRQuality(q quality) option { return func(s settings) (settings, error) { switch q { case qualityStandard, qualityFair, qualityGood, qualityGreat, qualityExcellent: @@ -196,28 +199,32 @@ func Quality(q quality) option { } } -// TODO: add check of r -func BitRate(r int) option { +func VBRBitRate(r int) option { + return func(s settings) (settings, error) { + var vbrRates = []int{250, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500} + if s.vbr == "1" { + s.vbrBitRate = convRate(r, vbrRates) + return s, nil + } + return s, nil + } +} + +func CBRBitRate(r int) option { return func(s settings) (settings, error) { var ( - vbrRates = []int{2000, 4000, 6000, 8000, 10000, 12000, 14000, 16000, 18000, 20000} cbrRates256 = []int{128, 256, 512, 1024} cbrRates360 = []int{512, 1024, 2048, 3072} cbrRates720 = []int{1024, 2048, 4096, 6144} ) - if s.vbr == "1" { - s.bitRate = convRate(r, vbrRates) - return s, nil - } - switch s.res { case res720: - s.bitRate = convRate(r, cbrRates720) + s.cbrBitRate = convRate(r, cbrRates720) case res360: - s.bitRate = convRate(r, cbrRates360) + s.cbrBitRate = convRate(r, cbrRates360) case res256: - s.bitRate = convRate(r, cbrRates256) + s.cbrBitRate = convRate(r, cbrRates256) default: panic("bad resolution") } diff --git a/input/gvctrl/gvctrl_test.go b/input/gvctrl/gvctrl_test.go index 7314e5a6..e11ca244 100644 --- a/input/gvctrl/gvctrl_test.go +++ b/input/gvctrl/gvctrl_test.go @@ -151,28 +151,44 @@ func TestHeight(t *testing.T) { } } -func TestBitrate(t *testing.T) { +func TestVBRBitrate(t *testing.T) { tests := []struct { r int in settings want settings }{ { - r: 7000, + r: 300, in: settings{vbr: "1"}, want: settings{ - vbr: "1", - bitRate: "6000000", + vbr: "1", + vbrBitRate: "250000", }, }, { - r: 7500, + r: 400, in: settings{vbr: "1"}, want: settings{ - vbr: "1", - bitRate: "8000000", + vbr: "1", + vbrBitRate: "500000", }, }, + } + + for i, test := range tests { + got, _ := VBRBitRate(test.r)(test.in) + if got != test.want { + t.Errorf("did not get expected result for test: %d\nGot: %v\nWant: %v", i, got, test.want) + } + } +} + +func TestCBRBitrate(t *testing.T) { + tests := []struct { + r int + in settings + want settings + }{ { r: 600, in: settings{ @@ -180,9 +196,9 @@ func TestBitrate(t *testing.T) { res: res256, }, want: settings{ - vbr: "0", - res: res256, - bitRate: "512000", + vbr: "0", + res: res256, + cbrBitRate: "512000", }, }, { @@ -192,9 +208,9 @@ func TestBitrate(t *testing.T) { res: res256, }, want: settings{ - vbr: "0", - res: res256, - bitRate: "128000", + vbr: "0", + res: res256, + cbrBitRate: "128000", }, }, { @@ -204,9 +220,9 @@ func TestBitrate(t *testing.T) { res: res360, }, want: settings{ - vbr: "0", - res: res360, - bitRate: "2048000", + vbr: "0", + res: res360, + cbrBitRate: "2048000", }, }, { @@ -216,15 +232,15 @@ func TestBitrate(t *testing.T) { res: res720, }, want: settings{ - vbr: "0", - res: res720, - bitRate: "1024000", + vbr: "0", + res: res720, + cbrBitRate: "1024000", }, }, } for i, test := range tests { - got, _ := BitRate(test.r)(test.in) + got, _ := CBRBitRate(test.r)(test.in) if got != test.want { t.Errorf("did not get expected result for test: %d\nGot: %v\nWant: %v", i, got, test.want) } @@ -281,28 +297,43 @@ func TestPopulateForm(t *testing.T) { }, { in: settings{ - codec: codecH265, - res: defaultRes, - frameRate: defaultFrameRate, - vbr: defaultVBR, - quality: defaultQuality, - bitRate: defaultBitRate, - refresh: defaultRefresh, + codec: codecH265, + res: defaultRes, + frameRate: defaultFrameRate, + vbr: defaultVBR, + quality: defaultQuality, + vbrBitRate: defaultVBRBitRate, + cbrBitRate: defaultCBRBitRate, + refresh: defaultRefresh, }, want: "dwConnType=5&mpeg_type=28&dwflicker_hz=0&szResolution=6400360&dwFrameRate=25000&vbr_enable=0&max_bit_rate=512000&custom_rate_control_type=0&custom_bitrate=0&custom_qp_init=25&custom_qp_min=10&custom_qp_max=40&gop_N=2000&dwEncProfile=1&dwEncLevel=31&dwEntropy=0&u8PreAlarmBuf=1&u32PostAlarmBuf2Disk=1&u8SplitInterval=5&bEnableIO=1&bEbIoIn=1&bEbIoIn1=1&bOSDFontSize=0&bEnableOSDCameraName=1&bCamNamePos=2&bEnableOSDDate=1&bDatePos=2&bEnableOSDTime=1&bTimePos=2&szOsdCamName=Camera&u16PostAlarmBuf=1&dwCameraId=1&LangCode=undefined&Recflag=0&submit=Apply", }, { in: settings{ - codec: codecMJPEG, - res: defaultRes, - frameRate: defaultFrameRate, - vbr: defaultVBR, - quality: defaultQuality, - bitRate: defaultBitRate, - refresh: defaultRefresh, + codec: codecMJPEG, + res: defaultRes, + frameRate: defaultFrameRate, + vbr: defaultVBR, + quality: defaultQuality, + vbrBitRate: defaultVBRBitRate, + cbrBitRate: defaultCBRBitRate, + refresh: defaultRefresh, }, want: "dwConnType=5&mpeg_type=4&dwflicker_hz=0&szResolution=6400360&dwFrameRate=25000&vbr_enable=1&dwVbrQuality=2&vbrmaxbitrate=500000&custom_qp_init=25&gop_N=1500&u8PreAlarmBuf=1&u32PostAlarmBuf2Disk=1&u8SplitInterval=5&bEnableIO=1&bEbIoIn=1&bEbIoIn1=1&bOSDFontSize=0&bEnableOSDCameraName=1&bCamNamePos=2&bEnableOSDDate=1&bDatePos=2&bEnableOSDTime=1&bTimePos=2&szOsdCamName=Camera&u16PostAlarmBuf=1&dwCameraId=1&LangCode=undefined&Recflag=0&submit=Apply", }, + { + in: settings{ + codec: codecH264, + res: defaultRes, + frameRate: defaultFrameRate, + vbr: "1", + quality: defaultQuality, + vbrBitRate: defaultVBRBitRate, + cbrBitRate: defaultCBRBitRate, + refresh: defaultRefresh, + }, + want: "dwConnType=5&mpeg_type=10&dwflicker_hz=0&szResolution=6400360&dwFrameRate=25000&vbr_enable=1&dwVbrQuality=2&vbrmaxbitrate=250000&custom_rate_control_type=0&custom_bitrate=0&custom_qp_init=25&custom_qp_min=10&custom_qp_max=40&gop_N=2000&dwEncProfile=1&dwEncLevel=31&dwEntropy=0&u8PreAlarmBuf=1&u32PostAlarmBuf2Disk=1&u8SplitInterval=5&bEnableIO=1&bEbIoIn=1&bEbIoIn1=1&bOSDFontSize=0&bEnableOSDCameraName=1&bCamNamePos=2&bEnableOSDDate=1&bDatePos=2&bEnableOSDTime=1&bTimePos=2&szOsdCamName=Camera&u16PostAlarmBuf=1&dwCameraId=1&LangCode=undefined&Recflag=0&submit=Apply", + }, } for i, test := range tests { diff --git a/input/gvctrl/utils.go b/input/gvctrl/utils.go index 078438ed..74b527d5 100644 --- a/input/gvctrl/utils.go +++ b/input/gvctrl/utils.go @@ -81,11 +81,11 @@ func populateForm(s settings) url.Values { switch s.vbr { case "0": f.Set("vbr_enable", "0") - f.Set("max_bit_rate", s.bitRate) + f.Set("max_bit_rate", s.cbrBitRate) case "1": f.Set("vbr_enable", "1") - f.Set("dwVbrQuality", s.vbr) - f.Set("vbrmaxbitrate", s.bitRate) + f.Set("dwVbrQuality", string(s.quality)) + f.Set("vbrmaxbitrate", s.vbrBitRate) default: panic("invalid vbrEnable parameter") }