Live video on the AT Protocol
79
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v0.8.1 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}