github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/h264/sps_test.go (about)

     1  package h264
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  )
     8  
     9  func TestSPSUnmarshal(t *testing.T) {
    10  	for _, ca := range []struct {
    11  		name   string
    12  		byts   []byte
    13  		sps    SPS
    14  		width  int
    15  		height int
    16  		fps    float64
    17  	}{
    18  		{
    19  			"352x288",
    20  			[]byte{
    21  				0x67, 0x64, 0x00, 0x0c, 0xac, 0x3b, 0x50, 0xb0,
    22  				0x4b, 0x42, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
    23  				0x00, 0x03, 0x00, 0x3d, 0x08,
    24  			},
    25  			SPS{
    26  				ProfileIdc:                     100,
    27  				LevelIdc:                       12,
    28  				ChromaFormatIdc:                1,
    29  				Log2MaxFrameNumMinus4:          6,
    30  				PicOrderCntType:                2,
    31  				MaxNumRefFrames:                1,
    32  				GapsInFrameNumValueAllowedFlag: true,
    33  				PicWidthInMbsMinus1:            21,
    34  				PicHeightInMapUnitsMinus1:      17,
    35  				FrameMbsOnlyFlag:               true,
    36  				Direct8x8InferenceFlag:         true,
    37  				VUI: &SPS_VUI{
    38  					TimingInfo: &SPS_TimingInfo{
    39  						NumUnitsInTick:     1,
    40  						TimeScale:          30,
    41  						FixedFrameRateFlag: true,
    42  					},
    43  				},
    44  			},
    45  			352,
    46  			288,
    47  			15,
    48  		},
    49  		{
    50  			"1280x720",
    51  			[]byte{
    52  				0x67, 0x64, 0x00, 0x1f, 0xac, 0xd9, 0x40, 0x50,
    53  				0x05, 0xbb, 0x01, 0x6c, 0x80, 0x00, 0x00, 0x03,
    54  				0x00, 0x80, 0x00, 0x00, 0x1e, 0x07, 0x8c, 0x18,
    55  				0xcb,
    56  			},
    57  			SPS{
    58  				ProfileIdc:                  100,
    59  				LevelIdc:                    31,
    60  				ChromaFormatIdc:             1,
    61  				Log2MaxPicOrderCntLsbMinus4: 2,
    62  				MaxNumRefFrames:             4,
    63  				PicWidthInMbsMinus1:         79,
    64  				PicHeightInMapUnitsMinus1:   44,
    65  				FrameMbsOnlyFlag:            true,
    66  				Direct8x8InferenceFlag:      true,
    67  				VUI: &SPS_VUI{
    68  					AspectRatioInfoPresentFlag: true,
    69  					AspectRatioIdc:             1,
    70  					VideoSignalTypePresentFlag: true,
    71  					VideoFormat:                5,
    72  					VideoFullRangeFlag:         true,
    73  					TimingInfo: &SPS_TimingInfo{
    74  						NumUnitsInTick: 1,
    75  						TimeScale:      60,
    76  					},
    77  					BitstreamRestriction: &SPS_BitstreamRestriction{
    78  						MotionVectorsOverPicBoundariesFlag: true,
    79  						Log2MaxMvLengthHorizontal:          11,
    80  						Log2MaxMvLengthVertical:            11,
    81  						MaxNumReorderFrames:                2,
    82  						MaxDecFrameBuffering:               4,
    83  					},
    84  				},
    85  			},
    86  			1280,
    87  			720,
    88  			30,
    89  		},
    90  		{
    91  			"1920x1080 baseline",
    92  			[]byte{
    93  				0x67, 0x42, 0xc0, 0x28, 0xd9, 0x00, 0x78, 0x02,
    94  				0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04,
    95  				0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc9, 0x20,
    96  			},
    97  			SPS{
    98  				ProfileIdc:                66,
    99  				ChromaFormatIdc:           1,
   100  				ConstraintSet0Flag:        true,
   101  				ConstraintSet1Flag:        true,
   102  				LevelIdc:                  40,
   103  				PicOrderCntType:           2,
   104  				MaxNumRefFrames:           3,
   105  				PicWidthInMbsMinus1:       119,
   106  				PicHeightInMapUnitsMinus1: 67,
   107  				FrameMbsOnlyFlag:          true,
   108  				Direct8x8InferenceFlag:    true,
   109  				FrameCropping: &SPS_FrameCropping{
   110  					BottomOffset: 4,
   111  				},
   112  				VUI: &SPS_VUI{
   113  					TimingInfo: &SPS_TimingInfo{
   114  						NumUnitsInTick: 1,
   115  						TimeScale:      60,
   116  					},
   117  					BitstreamRestriction: &SPS_BitstreamRestriction{
   118  						MotionVectorsOverPicBoundariesFlag: true,
   119  						Log2MaxMvLengthHorizontal:          11,
   120  						Log2MaxMvLengthVertical:            11,
   121  						MaxDecFrameBuffering:               3,
   122  					},
   123  				},
   124  			},
   125  			1920,
   126  			1080,
   127  			30,
   128  		},
   129  		{
   130  			"1920x1080 nvidia",
   131  			[]byte{
   132  				0x67, 0x64, 0x00, 0x28, 0xac, 0xd9, 0x40, 0x78,
   133  				0x02, 0x27, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00,
   134  				0x04, 0x00, 0x00, 0x03, 0x00, 0xf0, 0x3c, 0x60,
   135  				0xc6, 0x58,
   136  			},
   137  			SPS{
   138  				ProfileIdc:                  100,
   139  				LevelIdc:                    40,
   140  				ChromaFormatIdc:             1,
   141  				Log2MaxPicOrderCntLsbMinus4: 2,
   142  				MaxNumRefFrames:             4,
   143  				PicWidthInMbsMinus1:         119,
   144  				PicHeightInMapUnitsMinus1:   67,
   145  				FrameMbsOnlyFlag:            true,
   146  				Direct8x8InferenceFlag:      true,
   147  				FrameCropping: &SPS_FrameCropping{
   148  					BottomOffset: 4,
   149  				},
   150  				VUI: &SPS_VUI{
   151  					TimingInfo: &SPS_TimingInfo{
   152  						NumUnitsInTick: 1,
   153  						TimeScale:      60,
   154  					},
   155  					BitstreamRestriction: &SPS_BitstreamRestriction{
   156  						MotionVectorsOverPicBoundariesFlag: true,
   157  						Log2MaxMvLengthHorizontal:          11,
   158  						Log2MaxMvLengthVertical:            11,
   159  						MaxNumReorderFrames:                2,
   160  						MaxDecFrameBuffering:               4,
   161  					},
   162  				},
   163  			},
   164  			1920,
   165  			1080,
   166  			30,
   167  		},
   168  		{
   169  			"1920x1080",
   170  			[]byte{
   171  				0x67, 0x64, 0x00, 0x29, 0xac, 0x13, 0x31, 0x40,
   172  				0x78, 0x04, 0x47, 0xde, 0x03, 0xea, 0x02, 0x02,
   173  				0x03, 0xe0, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00,
   174  				0x00, 0x06, 0x52, // 0x80,
   175  			},
   176  			SPS{
   177  				ProfileIdc:                  100,
   178  				LevelIdc:                    41,
   179  				ChromaFormatIdc:             1,
   180  				Log2MaxFrameNumMinus4:       8,
   181  				Log2MaxPicOrderCntLsbMinus4: 5,
   182  				MaxNumRefFrames:             4,
   183  				PicWidthInMbsMinus1:         119,
   184  				PicHeightInMapUnitsMinus1:   33,
   185  				Direct8x8InferenceFlag:      true,
   186  				FrameCropping: &SPS_FrameCropping{
   187  					BottomOffset: 2,
   188  				},
   189  				VUI: &SPS_VUI{
   190  					AspectRatioInfoPresentFlag:   true,
   191  					AspectRatioIdc:               1,
   192  					OverscanInfoPresentFlag:      true,
   193  					OverscanAppropriateFlag:      true,
   194  					VideoSignalTypePresentFlag:   true,
   195  					VideoFormat:                  5,
   196  					ColourDescriptionPresentFlag: true,
   197  					ColourPrimaries:              1,
   198  					TransferCharacteristics:      1,
   199  					MatrixCoefficients:           1,
   200  					ChromaLocInfoPresentFlag:     true,
   201  					TimingInfo: &SPS_TimingInfo{
   202  						NumUnitsInTick:     1,
   203  						TimeScale:          50,
   204  						FixedFrameRateFlag: true,
   205  					},
   206  					PicStructPresentFlag: true,
   207  				},
   208  			},
   209  			1920,
   210  			1080,
   211  			25,
   212  		},
   213  		{
   214  			"hikvision",
   215  			[]byte{103, 100, 0, 32, 172, 23, 42, 1, 64, 30, 104, 64, 0, 1, 194, 0, 0, 87, 228, 33},
   216  			SPS{
   217  				ProfileIdc:                  100,
   218  				LevelIdc:                    32,
   219  				ChromaFormatIdc:             1,
   220  				Log2MaxPicOrderCntLsbMinus4: 4,
   221  				MaxNumRefFrames:             1,
   222  				PicWidthInMbsMinus1:         79,
   223  				PicHeightInMapUnitsMinus1:   59,
   224  				FrameMbsOnlyFlag:            true,
   225  				Direct8x8InferenceFlag:      true,
   226  				Log2MaxFrameNumMinus4:       10,
   227  				VUI: &SPS_VUI{
   228  					TimingInfo: &SPS_TimingInfo{
   229  						NumUnitsInTick:     1800,
   230  						TimeScale:          90000,
   231  						FixedFrameRateFlag: true,
   232  					},
   233  				},
   234  			},
   235  			1280,
   236  			960,
   237  			25,
   238  		},
   239  		{
   240  			"scaling matrix",
   241  			[]byte{
   242  				103, 100, 0, 50, 173, 132, 1, 12, 32, 8, 97, 0, 67, 8, 2,
   243  				24, 64, 16, 194, 0, 132, 59, 80, 20, 0, 90, 211,
   244  				112, 16, 16, 20, 0, 0, 3, 0, 4, 0, 0, 3, 0, 162, 16,
   245  			},
   246  			SPS{
   247  				ProfileIdc:      100,
   248  				LevelIdc:        50,
   249  				ChromaFormatIdc: 1,
   250  				ScalingList4x4: [][]int32{
   251  					{
   252  						16, 16, 16, 16, 16, 16, 16, 16,
   253  						16, 16, 16, 16, 16, 16, 16, 16,
   254  					},
   255  					{
   256  						16, 16, 16, 16, 16, 16, 16, 16,
   257  						16, 16, 16, 16, 16, 16, 16, 16,
   258  					},
   259  					{
   260  						16, 16, 16, 16, 16, 16, 16, 16,
   261  						16, 16, 16, 16, 16, 16, 16, 16,
   262  					},
   263  					{
   264  						16, 16, 16, 16, 16, 16, 16, 16,
   265  						16, 16, 16, 16, 16, 16, 16, 16,
   266  					},
   267  					{
   268  						16, 16, 16, 16, 16, 16, 16, 16,
   269  						16, 16, 16, 16, 16, 16, 16, 16,
   270  					},
   271  					{
   272  						16, 16, 16, 16, 16, 16, 16, 16,
   273  						16, 16, 16, 16, 16, 16, 16, 16,
   274  					},
   275  				},
   276  				UseDefaultScalingMatrix4x4Flag: []bool{
   277  					false, false, false, false, false, false,
   278  				},
   279  				Log2MaxFrameNumMinus4:          6,
   280  				PicOrderCntType:                2,
   281  				MaxNumRefFrames:                1,
   282  				GapsInFrameNumValueAllowedFlag: true,
   283  				PicWidthInMbsMinus1:            159,
   284  				PicHeightInMapUnitsMinus1:      89,
   285  				FrameMbsOnlyFlag:               true,
   286  				Direct8x8InferenceFlag:         true,
   287  				VUI: &SPS_VUI{
   288  					VideoSignalTypePresentFlag:   true,
   289  					VideoFormat:                  5,
   290  					VideoFullRangeFlag:           true,
   291  					ColourDescriptionPresentFlag: true,
   292  					ColourPrimaries:              1,
   293  					TransferCharacteristics:      1,
   294  					MatrixCoefficients:           1,
   295  					TimingInfo: &SPS_TimingInfo{
   296  						NumUnitsInTick:     1,
   297  						TimeScale:          40,
   298  						FixedFrameRateFlag: true,
   299  					},
   300  				},
   301  			},
   302  			2560,
   303  			1440,
   304  			20,
   305  		},
   306  		{
   307  			"1920x1080 nvenc hrd",
   308  			[]byte{
   309  				103, 100, 0, 42, 172, 44, 172, 7,
   310  				128, 34, 126, 92, 5, 168, 8, 8,
   311  				10, 0, 0, 7, 208, 0, 3, 169,
   312  				129, 192, 0, 0, 76, 75, 0, 0,
   313  				38, 37, 173, 222, 92, 20,
   314  			},
   315  			SPS{
   316  				ProfileIdc:                  100,
   317  				LevelIdc:                    42,
   318  				ChromaFormatIdc:             1,
   319  				Log2MaxFrameNumMinus4:       4,
   320  				Log2MaxPicOrderCntLsbMinus4: 4,
   321  				MaxNumRefFrames:             2,
   322  				PicWidthInMbsMinus1:         119,
   323  				PicHeightInMapUnitsMinus1:   67,
   324  				FrameMbsOnlyFlag:            true,
   325  				Direct8x8InferenceFlag:      true,
   326  				FrameCropping: &SPS_FrameCropping{
   327  					BottomOffset: 4,
   328  				},
   329  				VUI: &SPS_VUI{
   330  					AspectRatioInfoPresentFlag:   true,
   331  					AspectRatioIdc:               1,
   332  					VideoSignalTypePresentFlag:   true,
   333  					VideoFormat:                  5,
   334  					ColourDescriptionPresentFlag: true,
   335  					ColourPrimaries:              1,
   336  					TransferCharacteristics:      1,
   337  					MatrixCoefficients:           1,
   338  					TimingInfo: &SPS_TimingInfo{
   339  						NumUnitsInTick:     1000,
   340  						TimeScale:          120000,
   341  						FixedFrameRateFlag: true,
   342  					},
   343  					NalHRD: &SPS_HRD{
   344  						BitRateValueMinus1:                 []uint32{39061},
   345  						CpbSizeValueMinus1:                 []uint32{156249},
   346  						CbrFlag:                            []bool{true},
   347  						InitialCpbRemovalDelayLengthMinus1: 23,
   348  						CpbRemovalDelayLengthMinus1:        15,
   349  						DpbOutputDelayLengthMinus1:         5,
   350  						TimeOffsetLength:                   24,
   351  					},
   352  					PicStructPresentFlag: true,
   353  				},
   354  			},
   355  			1920,
   356  			1080,
   357  			60,
   358  		},
   359  		{
   360  			"1920x1080 hikvision nal hrd + vcl hrd",
   361  			[]byte{
   362  				103, 77, 0, 41, 154, 100, 3, 192,
   363  				17, 63, 46, 2, 220, 4, 4, 5,
   364  				0, 0, 3, 3, 232, 0, 0, 195,
   365  				80, 232, 96, 0, 186, 180, 0, 2,
   366  				234, 196, 187, 203, 141, 12, 0, 23,
   367  				86, 128, 0, 93, 88, 151, 121, 112,
   368  				160,
   369  			},
   370  			SPS{
   371  				ProfileIdc:                  77,
   372  				ChromaFormatIdc:             1,
   373  				LevelIdc:                    41,
   374  				Log2MaxFrameNumMinus4:       5,
   375  				Log2MaxPicOrderCntLsbMinus4: 5,
   376  				MaxNumRefFrames:             1,
   377  				PicWidthInMbsMinus1:         119,
   378  				PicHeightInMapUnitsMinus1:   67,
   379  				FrameMbsOnlyFlag:            true,
   380  				Direct8x8InferenceFlag:      true,
   381  				FrameCropping: &SPS_FrameCropping{
   382  					BottomOffset: 4,
   383  				},
   384  				VUI: &SPS_VUI{
   385  					AspectRatioInfoPresentFlag:   true,
   386  					AspectRatioIdc:               1,
   387  					VideoSignalTypePresentFlag:   true,
   388  					VideoFormat:                  5,
   389  					VideoFullRangeFlag:           true,
   390  					ColourDescriptionPresentFlag: true,
   391  					ColourPrimaries:              1,
   392  					TransferCharacteristics:      1,
   393  					MatrixCoefficients:           1,
   394  					TimingInfo: &SPS_TimingInfo{
   395  						NumUnitsInTick:     1000,
   396  						TimeScale:          50000,
   397  						FixedFrameRateFlag: true,
   398  					},
   399  					NalHRD: &SPS_HRD{
   400  						BitRateScale:                       4,
   401  						CpbSizeScale:                       3,
   402  						BitRateValueMinus1:                 []uint32{11948},
   403  						CpbSizeValueMinus1:                 []uint32{95585},
   404  						CbrFlag:                            []bool{false},
   405  						InitialCpbRemovalDelayLengthMinus1: 23,
   406  						CpbRemovalDelayLengthMinus1:        15,
   407  						DpbOutputDelayLengthMinus1:         5,
   408  						TimeOffsetLength:                   24,
   409  					},
   410  					VclHRD: &SPS_HRD{
   411  						BitRateScale:                       4,
   412  						CpbSizeScale:                       3,
   413  						BitRateValueMinus1:                 []uint32{11948},
   414  						CpbSizeValueMinus1:                 []uint32{95585},
   415  						CbrFlag:                            []bool{false},
   416  						InitialCpbRemovalDelayLengthMinus1: 23,
   417  						CpbRemovalDelayLengthMinus1:        15,
   418  						DpbOutputDelayLengthMinus1:         5,
   419  						TimeOffsetLength:                   24,
   420  					},
   421  					PicStructPresentFlag: true,
   422  				},
   423  			},
   424  			1920,
   425  			1080,
   426  			25,
   427  		},
   428  		{
   429  			"1920x1080 mbs_only_flag = 0",
   430  			[]byte{
   431  				0x67, 0x4d, 0x40, 0x28, 0xab, 0x60, 0x3c, 0x02,
   432  				0x23, 0xef, 0x01, 0x10, 0x00, 0x00, 0x03, 0x00,
   433  				0x10, 0x00, 0x00, 0x03, 0x03, 0x2e, 0x94, 0x00,
   434  				0x35, 0x64, 0x06, 0xb2, 0x85, 0x08, 0x0e, 0xe2,
   435  				0xc5, 0x22, 0xc0,
   436  			},
   437  			SPS{
   438  				ProfileIdc:                  77,
   439  				ChromaFormatIdc:             1,
   440  				ConstraintSet1Flag:          true,
   441  				LevelIdc:                    40,
   442  				Log2MaxFrameNumMinus4:       1,
   443  				Log2MaxPicOrderCntLsbMinus4: 2,
   444  				MaxNumRefFrames:             2,
   445  				PicWidthInMbsMinus1:         119,
   446  				PicHeightInMapUnitsMinus1:   33,
   447  				Direct8x8InferenceFlag:      true,
   448  				FrameCropping: &SPS_FrameCropping{
   449  					BottomOffset: 2,
   450  				},
   451  				VUI: &SPS_VUI{
   452  					AspectRatioInfoPresentFlag: true,
   453  					AspectRatioIdc:             1,
   454  					TimingInfo: &SPS_TimingInfo{
   455  						NumUnitsInTick:     1,
   456  						TimeScale:          50,
   457  						FixedFrameRateFlag: true,
   458  					},
   459  					NalHRD: &SPS_HRD{
   460  						BitRateScale:                       4,
   461  						CpbSizeScale:                       10,
   462  						BitRateValueMinus1:                 []uint32{3416},
   463  						CpbSizeValueMinus1:                 []uint32{213},
   464  						CbrFlag:                            []bool{false},
   465  						InitialCpbRemovalDelayLengthMinus1: 20,
   466  						CpbRemovalDelayLengthMinus1:        5,
   467  						DpbOutputDelayLengthMinus1:         1,
   468  					},
   469  					PicStructPresentFlag: true,
   470  					BitstreamRestriction: &SPS_BitstreamRestriction{
   471  						MotionVectorsOverPicBoundariesFlag: true,
   472  						MaxBytesPerPicDenom:                2,
   473  						Log2MaxMvLengthHorizontal:          10,
   474  						Log2MaxMvLengthVertical:            9,
   475  						MaxNumReorderFrames:                1,
   476  						MaxDecFrameBuffering:               4,
   477  					},
   478  				},
   479  			},
   480  			1920,
   481  			1080,
   482  			25,
   483  		},
   484  	} {
   485  		t.Run(ca.name, func(t *testing.T) {
   486  			var sps SPS
   487  			err := sps.Unmarshal(ca.byts)
   488  			require.NoError(t, err)
   489  			require.Equal(t, ca.sps, sps)
   490  			require.Equal(t, ca.width, sps.Width())
   491  			require.Equal(t, ca.height, sps.Height())
   492  			require.Equal(t, ca.fps, sps.FPS())
   493  		})
   494  	}
   495  }
   496  
   497  func BenchmarkSPSUnmarshal(b *testing.B) {
   498  	for i := 0; i < b.N; i++ {
   499  		var sps SPS
   500  		sps.Unmarshal([]byte{ //nolint:errcheck
   501  			103, 77, 0, 41, 154, 100, 3, 192,
   502  			17, 63, 46, 2, 220, 4, 4, 5,
   503  			0, 0, 3, 3, 232, 0, 0, 195,
   504  			80, 232, 96, 0, 186, 180, 0, 2,
   505  			234, 196, 187, 203, 141, 12, 0, 23,
   506  			86, 128, 0, 93, 88, 151, 121, 112,
   507  			160,
   508  		})
   509  	}
   510  }
   511  
   512  func FuzzSPSUnmarshal(f *testing.F) {
   513  	f.Fuzz(func(_ *testing.T, b []byte) {
   514  		var sps SPS
   515  		sps.Unmarshal(b) //nolint:errcheck
   516  	})
   517  }