Live video on the AT Protocol
at eli/multitesting 323 lines 5.9 kB view raw
1package renditions 2 3import ( 4 "encoding/json" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 "stream.place/streamplace/pkg/streamplace" 9) 10 11func seg(width int, height int, fpsNum int, fpsDen int) *streamplace.Segment { 12 return &streamplace.Segment{ 13 Video: []*streamplace.Segment_Video{ 14 { 15 Width: int64(width), 16 Height: int64(height), 17 Framerate: &streamplace.Segment_Framerate{ 18 Num: int64(fpsNum), 19 Den: int64(fpsDen), 20 }, 21 }, 22 }, 23 } 24} 25 26var cases = []struct { 27 name string 28 spseg *streamplace.Segment 29 lp string 30}{ 31 { 32 name: "4K 60fps", 33 spseg: seg(3840, 2160, 60, 1), 34 lp: ` 35 [ 36 { 37 "name": "1080p", 38 "height": 1080, 39 "bitrate": 6000000, 40 "profile": "h264constrainedhigh" 41 }, 42 { 43 "name": "720p", 44 "height": 720, 45 "bitrate": 3000000, 46 "profile": "h264constrainedhigh" 47 }, 48 { 49 "name": "360p", 50 "height": 360, 51 "bitrate": 1000000, 52 "profile": "h264constrainedhigh", 53 "fps": 60, 54 "fpsDen": 2 55 }, 56 { 57 "name": "240p", 58 "height": 240, 59 "bitrate": 500000, 60 "profile": "h264constrainedhigh", 61 "fps": 60, 62 "fpsDen": 2 63 }, 64 { 65 "name": "160p", 66 "height": 160, 67 "bitrate": 250000, 68 "profile": "h264baseline", 69 "fps": 60, 70 "fpsDen": 2 71 } 72 ] 73 `, 74 }, 75 { 76 name: "2K with fractional framerate", 77 spseg: seg(2160, 1440, 60000, 1001), 78 lp: ` 79 [ 80 { 81 "name": "1080p", 82 "height": 1080, 83 "bitrate": 6000000, 84 "profile": "h264constrainedhigh" 85 }, 86 { 87 "name": "720p", 88 "height": 720, 89 "bitrate": 3000000, 90 "profile": "h264constrainedhigh" 91 }, 92 { 93 "name": "360p", 94 "height": 360, 95 "bitrate": 1000000, 96 "profile": "h264constrainedhigh", 97 "fps": 60000, 98 "fpsDen": 2002 99 }, 100 { 101 "name": "240p", 102 "height": 240, 103 "bitrate": 500000, 104 "profile": "h264constrainedhigh", 105 "fps": 60000, 106 "fpsDen": 2002 107 }, 108 { 109 "name": "160p", 110 "height": 160, 111 "bitrate": 250000, 112 "profile": "h264baseline", 113 "fps": 60000, 114 "fpsDen": 2002 115 } 116 ] 117 `, 118 }, 119 { 120 name: "720p 50fps", 121 spseg: seg(1280, 720, 50, 1), 122 lp: ` 123 [ 124 { 125 "name": "360p", 126 "height": 360, 127 "bitrate": 1000000, 128 "profile": "h264constrainedhigh", 129 "fps": 50, 130 "fpsDen": 2 131 }, 132 { 133 "name": "240p", 134 "height": 240, 135 "bitrate": 500000, 136 "profile": "h264constrainedhigh", 137 "fps": 50, 138 "fpsDen": 2 139 }, 140 { 141 "name": "160p", 142 "height": 160, 143 "bitrate": 250000, 144 "profile": "h264baseline", 145 "fps": 50, 146 "fpsDen": 2 147 } 148 ] 149 `, 150 }, 151 { 152 name: "720p 30fps", 153 spseg: seg(1280, 720, 30, 1), 154 lp: ` 155 [ 156 { 157 "name": "360p", 158 "height": 360, 159 "bitrate": 1000000, 160 "profile": "h264constrainedhigh" 161 }, 162 { 163 "name": "240p", 164 "height": 240, 165 "bitrate": 500000, 166 "profile": "h264constrainedhigh" 167 }, 168 { 169 "name": "160p", 170 "height": 160, 171 "bitrate": 250000, 172 "profile": "h264baseline" 173 } 174 ] 175 `, 176 }, 177 { 178 name: "720p 25fps", 179 spseg: seg(1280, 720, 25, 1), 180 lp: ` 181 [ 182 { 183 "name": "360p", 184 "height": 360, 185 "bitrate": 1000000, 186 "profile": "h264constrainedhigh" 187 }, 188 { 189 "name": "240p", 190 "height": 240, 191 "bitrate": 500000, 192 "profile": "h264constrainedhigh" 193 }, 194 { 195 "name": "160p", 196 "height": 160, 197 "bitrate": 250000, 198 "profile": "h264baseline" 199 } 200 ] 201 `, 202 }, 203 { 204 name: "Vertical video 60fps", 205 spseg: seg(480, 640, 60, 1), 206 lp: ` 207 [ 208 { 209 "name": "360p", 210 "width": 360, 211 "bitrate": 1000000, 212 "profile": "h264constrainedhigh", 213 "fps": 60, 214 "fpsDen": 2 215 }, 216 { 217 "name": "240p", 218 "width": 240, 219 "bitrate": 500000, 220 "profile": "h264constrainedhigh", 221 "fps": 60, 222 "fpsDen": 2 223 }, 224 { 225 "name": "160p", 226 "width": 160, 227 "bitrate": 250000, 228 "profile": "h264baseline", 229 "fps": 60, 230 "fpsDen": 2 231 } 232 ] 233 `, 234 }, 235} 236 237func TestRenditions(t *testing.T) { 238 for _, c := range cases { 239 t.Run(c.name, func(t *testing.T) { 240 rends, err := GenerateRenditions(c.spseg) 241 require.NoError(t, err) 242 lp := rends.ToLivepeerProfiles() 243 bs, err := json.Marshal(lp) 244 require.NoError(t, err) 245 require.JSONEq(t, c.lp, string(bs)) 246 }) 247 } 248} 249 250var singleCases = []struct { 251 name string 252 spseg *streamplace.Segment 253 lp string 254 dimensions []int 255}{ 256 { 257 name: "Nearly-Square Landscape 4K 60fps", 258 spseg: seg(3840, 3830, 60, 1), 259 dimensions: []int{1083, 1080}, 260 lp: ` 261 { 262 "name": "1080p", 263 "height": 1080, 264 "bitrate": 6000000, 265 "profile": "h264constrainedhigh" 266 } 267 `, 268 }, 269 { 270 name: "Nearly-Square Portrait 4K 60fps", 271 spseg: seg(3830, 3840, 60, 1), 272 dimensions: []int{1080, 1083}, 273 lp: ` 274 { 275 "name": "1080p", 276 "width": 1080, 277 "bitrate": 6000000, 278 "profile": "h264constrainedhigh" 279 } 280 `, 281 }, 282 { 283 name: "Stupidly-Wide Landscape 4K 60fps", 284 spseg: seg(5000, 2160, 60, 1), 285 dimensions: []int{1920, 829}, 286 lp: ` 287 { 288 "name": "1080p", 289 "width": 1920, 290 "bitrate": 6000000, 291 "profile": "h264constrainedhigh" 292 } 293 `, 294 }, 295 { 296 name: "Stupidly-Tall Portrait 4K 60fps", 297 spseg: seg(2160, 5000, 60, 1), 298 dimensions: []int{829, 1920}, 299 lp: ` 300 { 301 "name": "1080p", 302 "height": 1920, 303 "bitrate": 6000000, 304 "profile": "h264constrainedhigh" 305 } 306 `, 307 }, 308} 309 310func TestSingleRendition(t *testing.T) { 311 for _, c := range singleCases { 312 t.Run(c.name, func(t *testing.T) { 313 rends, err := GenerateRenditions(c.spseg) 314 require.NoError(t, err) 315 first := rends[0] 316 require.Equal(t, c.dimensions, []int{int(first.Width), int(first.Height)}) 317 lp := rends.ToLivepeerProfiles() 318 bs, err := json.Marshal(lp[0]) 319 require.NoError(t, err) 320 require.JSONEq(t, c.lp, string(bs)) 321 }) 322 } 323}