github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/h264/dts_extractor_test.go (about) 1 package h264 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/stretchr/testify/require" 8 ) 9 10 func TestDTSExtractor(t *testing.T) { 11 type sample struct { 12 au [][]byte 13 dts time.Duration 14 pts time.Duration 15 } 16 17 for _, ca := range []struct { 18 name string 19 sequence []sample 20 }{ 21 { 22 "with timing info", 23 []sample{ 24 { 25 [][]byte{ 26 { // SPS 27 0x67, 0x64, 0x00, 0x28, 0xac, 0xd9, 0x40, 0x78, 28 0x02, 0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 29 0x04, 0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 30 0xc6, 0x58, 31 }, 32 { // IDR 33 0x65, 0x88, 0x84, 0x00, 0x33, 0xff, 34 }, 35 }, 36 333333333 * time.Nanosecond, 37 333333333 * time.Nanosecond, 38 }, 39 { 40 [][]byte{{0x41, 0x9a, 0x21, 0x6c, 0x45, 0xff}}, 41 366666666 * time.Nanosecond, 42 366666666 * time.Nanosecond, 43 }, 44 { 45 [][]byte{{0x41, 0x9a, 0x42, 0x3c, 0x21, 0x93}}, 46 400000000 * time.Nanosecond, 47 400000000 * time.Nanosecond, 48 }, 49 { 50 [][]byte{{0x41, 0x9a, 0x63, 0x49, 0xe1, 0x0f}}, 51 433333333 * time.Nanosecond, 52 433333333 * time.Nanosecond, 53 }, 54 { 55 [][]byte{{0x41, 0x9a, 0x86, 0x49, 0xe1, 0x0f}}, 56 434333333 * time.Nanosecond, 57 533333333 * time.Nanosecond, 58 }, 59 { 60 [][]byte{{0x41, 0x9e, 0xa5, 0x42, 0x7f, 0xf9}}, 61 435333333 * time.Nanosecond, 62 500000000 * time.Nanosecond, 63 }, 64 { 65 [][]byte{{0x01, 0x9e, 0xc4, 0x69, 0x13, 0xff}}, 66 466666666 * time.Nanosecond, 67 466666666 * time.Nanosecond, 68 }, 69 { 70 [][]byte{{0x41, 0x9a, 0xc8, 0x4b, 0xa8, 0x42}}, 71 499999999 * time.Nanosecond, 72 600000000 * time.Nanosecond, 73 }, 74 { 75 [][]byte{ 76 { // IDR 77 0x65, 0x88, 0x84, 0x00, 0x33, 0xff, 78 }, 79 }, 80 533333332 * time.Nanosecond, 81 599999999 * time.Nanosecond, 82 }, 83 }, 84 }, 85 { 86 "no timing info", 87 []sample{ 88 { 89 [][]byte{ 90 { // SPS 91 0x27, 0x64, 0x00, 0x20, 0xac, 0x52, 0x18, 0x0f, 92 0x01, 0x17, 0xef, 0xff, 0x00, 0x01, 0x00, 0x01, 93 0x6a, 0x02, 0x02, 0x03, 0x6d, 0x85, 0x6b, 0xde, 94 0xf8, 0x08, 95 }, 96 { // IDR 97 0x25, 0xb8, 0x08, 0x02, 0x1f, 0xff, 98 }, 99 }, 100 850000000 * time.Nanosecond, 101 850000000 * time.Nanosecond, 102 }, 103 { 104 [][]byte{{0x21, 0xe1, 0x05, 0xc7, 0x38, 0xbf}}, 105 866666667 * time.Nanosecond, 106 866666667 * time.Nanosecond, 107 }, 108 { 109 [][]byte{{0x21, 0xe2, 0x09, 0xa1, 0xce, 0x0b}}, 110 883333334 * time.Nanosecond, 111 883333334 * time.Nanosecond, 112 }, 113 { 114 [][]byte{{0x21, 0xe3, 0x0d, 0xb1, 0xce, 0x02}}, 115 900000000 * time.Nanosecond, 116 900000000 * time.Nanosecond, 117 }, 118 { 119 [][]byte{{0x21, 0xe4, 0x11, 0x90, 0x73, 0x80}}, 120 916666667 * time.Nanosecond, 121 916666667 * time.Nanosecond, 122 }, 123 { 124 [][]byte{{0x21, 0xe5, 0x19, 0x0e, 0x70, 0x01}}, 125 917666667 * time.Nanosecond, 126 950000000 * time.Nanosecond, 127 }, 128 { 129 [][]byte{{0x01, 0xa9, 0x85, 0x7c, 0x93, 0xff}}, 130 933333334 * time.Nanosecond, 131 933333334 * time.Nanosecond, 132 }, 133 { 134 [][]byte{{0x21, 0xe6, 0x1d, 0x0e, 0x70, 0x01}}, 135 950000000 * time.Nanosecond, 136 966666667 * time.Nanosecond, 137 }, 138 { 139 [][]byte{{0x21, 0xe7, 0x21, 0x0e, 0x70, 0x01}}, 140 966666667 * time.Nanosecond, 141 983333334 * time.Nanosecond, 142 }, 143 { 144 [][]byte{{0x21, 0xe8, 0x25, 0x0e, 0x70, 0x01}}, 145 983333333 * time.Nanosecond, 146 1000000000 * time.Nanosecond, 147 }, 148 { 149 [][]byte{{0x21, 0xe9, 0x29, 0x0e, 0x70, 0x01}}, 150 1000000000 * time.Nanosecond, 151 1016666667 * time.Nanosecond, 152 }, 153 { 154 [][]byte{{0x21, 0xea, 0x31, 0x0e, 0x70, 0x01}}, 155 1016666666 * time.Nanosecond, 156 1050000000 * time.Nanosecond, 157 }, 158 { 159 [][]byte{{0x01, 0xaa, 0xcb, 0x7c, 0x93, 0xff}}, 160 1033333334 * time.Nanosecond, 161 1033333334 * time.Nanosecond, 162 }, 163 }, 164 }, 165 { 166 "poc increment = 1", 167 []sample{ 168 { 169 [][]byte{ 170 { // SPS 171 0x67, 0x64, 0x00, 0x2a, 0xac, 0x2c, 0x6a, 0x81, 172 0xe0, 0x08, 0x9f, 0x96, 0x6e, 0x02, 0x02, 0x02, 173 0x80, 0x00, 0x03, 0x84, 0x00, 0x00, 0xaf, 0xc8, 174 0x02, 175 }, 176 { // IDR 177 0x65, 0xb8, 0x00, 0x00, 0x0b, 0xc8, 178 }, 179 }, 180 61 * time.Millisecond, 181 61 * time.Millisecond, 182 }, 183 { 184 [][]byte{{0x61, 0xe0, 0x20, 0x00, 0x39, 0x37}}, 185 101 * time.Millisecond, 186 101 * time.Millisecond, 187 }, 188 { 189 [][]byte{{0x61, 0xe0, 0x40, 0x00, 0x59, 0x37}}, 190 141 * time.Millisecond, 191 141 * time.Millisecond, 192 }, 193 { 194 [][]byte{{0x61, 0xe0, 0x60, 0x00, 0x79, 0x37}}, 195 181 * time.Millisecond, 196 181 * time.Millisecond, 197 }, 198 }, 199 }, 200 { 201 "B-frames after IDR (OBS 29.1.3 QuickSync on Windows)", 202 []sample{ 203 { 204 [][]byte{ 205 { // SPS 206 0x27, 0x64, 0x00, 0x2a, 0xac, 0x2d, 0x90, 0x07, 207 0x80, 0x22, 0x7e, 0x5c, 0x05, 0xa8, 0x08, 0x08, 208 0x0a, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 209 0x03, 0x00, 0xf1, 0xd0, 0x80, 0x04, 0xc4, 0x80, 210 0x00, 0x09, 0x89, 0x68, 0xde, 0xf7, 0xc1, 0xda, 211 0x1c, 0x31, 0x92, 212 }, 213 { // IDR 214 0x65, 0x88, 0x80, 0x14, 0x3, 0xff, 0xde, 0x8, 0xe4, 0x74, 215 }, 216 }, 217 1916 * time.Millisecond, 218 1916 * time.Millisecond, 219 }, 220 { // b-frame 221 [][]byte{{0x41, 0x9e, 0x3, 0xe4, 0x3f, 0x0, 0x0, 0x3, 0x0, 0x0}}, 222 1917 * time.Millisecond, 223 1883 * time.Millisecond, 224 }, 225 { // b-frame 226 [][]byte{{0x1, 0x9e, 0x5, 0xd4, 0x7f, 0x0, 0x0, 0x3, 0x0, 0x0}}, 227 1918 * time.Millisecond, 228 1867 * time.Millisecond, 229 }, 230 { // p-frame 231 [][]byte{{0x1, 0x9e, 0x5, 0xf4, 0x7f, 0x0, 0x0, 0x3, 0x0, 0x0}}, 232 1919 * time.Millisecond, 233 1899 * time.Millisecond, 234 }, 235 { // p-frame 236 [][]byte{{0x1, 0x9e, 0x5, 0xf4, 0x7f, 0x0, 0x0, 0x3, 0x0, 0x0}}, 237 1920 * time.Millisecond, 238 1983 * time.Millisecond, 239 }, 240 }, 241 }, 242 { 243 "mbs_only_flag = 0", 244 []sample{ 245 { 246 [][]byte{ 247 { // SPS 248 0x67, 0x4d, 0x40, 0x28, 0xab, 0x60, 0x3c, 0x02, 249 0x23, 0xef, 0x01, 0x10, 0x00, 0x00, 0x03, 0x00, 250 0x10, 0x00, 0x00, 0x03, 0x03, 0x2e, 0x94, 0x00, 251 0x35, 0x64, 0x06, 0xb2, 0x85, 0x08, 0x0e, 0xe2, 252 0xc5, 0x22, 0xc0, 253 }, 254 {0x68, 0xca, 0x41, 0xf2}, // PPS 255 {0x6, 0x0, 0x6, 0x85, 0x7e, 0x40, 0x0, 0x0, 0x10, 0x1}, // SEI 256 {0x65, 0x88, 0x82, 0x80, 0x1f, 0xff, 0xfb, 0xf0, 0xa2, 0x88}, // IDR 257 {0x6, 0x1, 0x2, 0x4, 0x24, 0x80}, // SEI 258 {0x41, 0x9a, 0xc, 0x1c, 0x2f, 0xe4, 0xed, 0x23, 0xb5, 0x63}, // non-IDR 259 }, 260 0, 261 0, 262 }, 263 { 264 [][]byte{ 265 {0x6, 0x1, 0x2, 0x8, 0x14, 0x80}, // SEI 266 {0x41, 0x9a, 0x18, 0x2a, 0x1f, 0xeb, 0x2f, 0xa2, 0xb1, 0x7e}, // non-IDR 267 }, 268 40 * time.Millisecond, 269 40 * time.Millisecond, 270 }, 271 { 272 [][]byte{ 273 {0x6, 0x1, 0x2, 0xc, 0x24, 0x80}, // SEI 274 {0x41, 0x9a, 0x1c, 0x3a, 0xf, 0xfa, 0x55, 0xc2, 0x55, 0xea}, // non-IDR 275 }, 276 80 * time.Millisecond, 277 80 * time.Millisecond, 278 }, 279 }, 280 }, 281 { 282 "Log2MaxPicOrderCntLsbMinus4 = 12", 283 []sample{ 284 { 285 [][]byte{ 286 { // SPS 287 0x67, 0x42, 0xc0, 0x1e, 0x8c, 0x8d, 0x40, 0x50, 0x17, 0xfc, 0xb0, 0x0f, 0x08, 0x84, 0x6a, 288 }, 289 { // PPS 290 0x68, 0xce, 0x3c, 0x80, 291 }, 292 { // IDR 293 0x65, 0x88, 0x80, 0x14, 0x3, 0xff, 0xde, 0x8, 0xe4, 0x74, 294 }, 295 }, 296 0, 297 0, 298 }, 299 { 300 [][]byte{ 301 {0x61, 0x00, 0xf0, 0xe0, 0x00, 0x40, 0x00, 0xbe, 0x47, 0x9b}, // non-IDR 302 }, 303 40 * time.Millisecond, 304 40 * time.Millisecond, 305 }, 306 }, 307 }, 308 } { 309 t.Run(ca.name, func(t *testing.T) { 310 ex := NewDTSExtractor() 311 for _, sample := range ca.sequence { 312 dts, err := ex.Extract(sample.au, sample.pts) 313 require.NoError(t, err) 314 require.Equal(t, sample.dts, dts) 315 } 316 }) 317 } 318 } 319 320 func FuzzDTSExtractor(f *testing.F) { 321 ex := NewDTSExtractor() 322 f.Fuzz(func(_ *testing.T, b []byte, p uint64) { 323 if len(b) < 1 { 324 return 325 } 326 ex.Extract([][]byte{ //nolint:errcheck 327 { // SPS 328 0x27, 0x64, 0x00, 0x20, 0xac, 0x52, 0x18, 0x0f, 329 0x01, 0x17, 0xef, 0xff, 0x00, 0x01, 0x00, 0x01, 330 0x6a, 0x02, 0x02, 0x03, 0x6d, 0x85, 0x6b, 0xde, 331 0xf8, 0x08, 332 }, 333 b, 334 }, time.Duration(p)) 335 }) 336 }