Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(avc/slice): entire NALU consumed as slice header #272

Merged
merged 1 commit into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions avc/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ func ParseSliceHeader(nalu []byte, spsMap map[uint32]*SPS, ppsMap map[uint32]*PP
if sliceType != SLICE_I && sliceType != SLICE_SI {
sh.RefPicListModificationL0Flag = r.ReadFlag()
if sh.RefPicListModificationL0Flag {
refPicListL0Loop:
for {
sh.ModificationOfPicNumsIDC = uint32(r.ReadExpGolomb())
switch sh.ModificationOfPicNumsIDC {
Expand All @@ -216,17 +217,18 @@ func ParseSliceHeader(nalu []byte, spsMap map[uint32]*SPS, ppsMap map[uint32]*PP
case 2:
sh.LongTermPicNum = uint32(r.ReadExpGolomb())
case 3:
break
break refPicListL0Loop
}
if r.AccError() != nil {
break
break refPicListL0Loop
}
}
}
}
if sliceType == SLICE_B {
sh.RefPicListModificationL1Flag = r.ReadFlag()
if sh.RefPicListModificationL1Flag {
refPicListL1Loop:
for {
sh.ModificationOfPicNumsIDC = uint32(r.ReadExpGolomb())
switch sh.ModificationOfPicNumsIDC {
Expand All @@ -235,7 +237,10 @@ func ParseSliceHeader(nalu []byte, spsMap map[uint32]*SPS, ppsMap map[uint32]*PP
case 2:
sh.LongTermPicNum = uint32(r.ReadExpGolomb())
case 3:
break
break refPicListL1Loop
}
if r.AccError() != nil {
break refPicListL1Loop
}
}
}
Expand Down Expand Up @@ -299,6 +304,7 @@ func ParseSliceHeader(nalu []byte, spsMap map[uint32]*SPS, ppsMap map[uint32]*PP
} else {
sh.AdaptiveRefPicMarkingModeFlag = r.ReadFlag()
if sh.AdaptiveRefPicMarkingModeFlag {
adaptiveRefPicLoop:
for {
memoryManagementControlOperation := r.ReadExpGolomb()
switch memoryManagementControlOperation {
Expand All @@ -313,7 +319,10 @@ func ParseSliceHeader(nalu []byte, spsMap map[uint32]*SPS, ppsMap map[uint32]*PP
case 4:
sh.MaxLongTermFrameIdxPlus1 = uint32(r.ReadExpGolomb())
case 0:
break
break adaptiveRefPicLoop
}
if r.AccError() != nil {
break adaptiveRefPicLoop
}
}
}
Expand Down
57 changes: 56 additions & 1 deletion avc/slice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestSliceTypeParser(t *testing.T) {
}
}

func TestParseSliceHeader(t *testing.T) {
func TestParseSliceHeader_BlackFrame(t *testing.T) {
wantedHdr := SliceHeader{
SliceType: 7,
SliceQPDelta: 6,
Expand Down Expand Up @@ -65,3 +65,58 @@ func TestParseSliceHeader(t *testing.T) {
t.Error(diff)
}
}

func TestParseSliceHeader_TwoFrames(t *testing.T) {
wantedIdrHdr := SliceHeader{SliceType: SLICE_I, IDRPicID: 1, SliceQPDelta: 8, Size: 5}
wantedNonIdrHdr := SliceHeader{
SliceType: SLICE_P, FrameNum: 1, ModificationOfPicNumsIDC: 3, SliceQPDelta: 13,
Size: 5, NumRefIdxActiveOverrideFlag: true, RefPicListModificationL0Flag: true,
}

data, err := ioutil.ReadFile("testdata/two-frames.264")
if err != nil {
t.Error(err)
}
nalus, err := GetNalusFromSample(data)
if err != nil {
t.Error(err)
}
spsMap := make(map[uint32]*SPS, 1)
ppsMap := make(map[uint32]*PPS, 1)
var gotIdrHdr *SliceHeader
var gotNonIdrHdr *SliceHeader
for _, nalu := range nalus {
switch GetNaluType(nalu[0]) {
case NALU_SPS:
sps, err := ParseSPSNALUnit(nalu, true)
if err != nil {
t.Error(err)
}
spsMap[uint32(sps.ParameterID)] = sps
case NALU_PPS:
pps, err := ParsePPSNALUnit(nalu, spsMap)
if err != nil {
t.Error(err)
}
ppsMap[uint32(pps.PicParameterSetID)] = pps
case NALU_IDR:
gotIdrHdr, err = ParseSliceHeader(nalu, spsMap, ppsMap)
if err != nil {
t.Error(err)
}
case NALU_NON_IDR:
gotNonIdrHdr, err = ParseSliceHeader(nalu, spsMap, ppsMap)
if err != nil {
t.Error(err)
}
}
}
if diff := deep.Equal(wantedIdrHdr, *gotIdrHdr); diff != nil {
fmt.Printf("Got IDR Slice Header: %+v\n Diff is: ", *gotIdrHdr)
t.Error(diff)
}
if diff := deep.Equal(wantedNonIdrHdr, *gotNonIdrHdr); diff != nil {
fmt.Printf("Got NON_IDR Slice Header: %+v\n Diff is: ", *gotNonIdrHdr)
t.Error(diff)
}
}
Binary file added avc/testdata/two-frames.264
Binary file not shown.