Skip to content

Commit a916aaa

Browse files
committed
feat: add VVC NAL unit support to mp4ff-nallister
- Add VVC codec option (-c vvc) to command line interface - Change return type of Sample.PresentationTime() to int64 - Implement VVC AUD detection for Annex B stream processing
1 parent a819496 commit a916aaa

16 files changed

Lines changed: 379 additions & 32 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Basic VVC support with vvcC box and VvcDecoderConfigurationRecord
13+
- Support for parsing VVC NAL unit headers and listing types in mp4ff-nallister
1314
- Minimal AC-4 support by recognizing ac-4 as AudioSampleDescrition box
1415
- Support for Opus and dOps boxes
1516

1617
### Changed
1718

1819
- Makefile update to setup and run pre-commit with configuration
20+
- Return type of Sample.PresentationTime is now int64 instead of uint64
21+
This may happen together with edit lists (seen for VVC video)
1922

2023
## [0.49.0] - 2025-06-26
2124

cmd/mp4ff-nallister/main.go

Lines changed: 102 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ import (
1414
"github.com/Eyevinn/mp4ff/internal"
1515
"github.com/Eyevinn/mp4ff/mp4"
1616
"github.com/Eyevinn/mp4ff/sei"
17+
"github.com/Eyevinn/mp4ff/vvc"
1718
)
1819

1920
const (
2021
appName = "mp4ff-nallister"
2122
)
2223

23-
var usg = `%s lists NAL units and slice types of AVC or HEVC tracks of an mp4 (ISOBMFF) file
24+
var usg = `%s lists NAL units and slice types of AVC, HEVC, or VVC tracks of an mp4 (ISOBMFF) file
2425
or a file containing a byte stream in Annex B format.
2526
2627
Takes first video track in a progressive file and the first track in a fragmented file.
@@ -51,7 +52,7 @@ func parseOptions(fs *flag.FlagSet, args []string) (*options, error) {
5152
opts := options{}
5253

5354
fs.IntVar(&opts.maxNrSamples, "m", -1, "Max nr of samples to parse")
54-
fs.StringVar(&opts.codec, "c", "avc", "Codec to parse (avc or hevc)")
55+
fs.StringVar(&opts.codec, "c", "avc", "Codec to parse (avc, hevc, or vvc)")
5556
fs.IntVar(&opts.seiLevel, "sei", 0, "Level of SEI information (1 is interpret, 2 is dump hex)")
5657
fs.IntVar(&opts.printRaw, "raw", 0, "nr raw NAL unit bytes to print")
5758
fs.BoolVar(&opts.annexB, "annexb", false, "Input is Annex B stream file")
@@ -108,7 +109,8 @@ func run(args []string, stdout io.Writer) error {
108109
}
109110
var avcSPS *avc.SPS
110111
for i, frame := range frames {
111-
if o.codec == "avc" {
112+
switch o.codec {
113+
case "avc":
112114
if avcSPS == nil {
113115
for _, nalu := range frame {
114116
if avc.GetNaluType(nalu[0]) == avc.NALU_SPS {
@@ -120,8 +122,12 @@ func run(args []string, stdout io.Writer) error {
120122
}
121123
}
122124
err = printAVCNalus(stdout, avcSPS, frame, i+1, 0, o.seiLevel, o.printPsHex, o.printRaw)
123-
} else {
125+
case "hevc":
124126
err = printHEVCNalus(stdout, frame, i+1, 0, o.seiLevel, o.printPsHex, o.printRaw)
127+
case "vvc":
128+
err = printVVCNalus(stdout, frame, i+1, 0, o.seiLevel, o.printPsHex, o.printRaw)
129+
default:
130+
return fmt.Errorf("unsupported codec: %s", o.codec)
125131
}
126132
if err != nil {
127133
return fmt.Errorf("printing error: %w", err)
@@ -175,6 +181,8 @@ func parseProgressiveMp4(w io.Writer, f *mp4.File, maxNrSamples int, codec strin
175181
}
176182
} else if stbl.Stsd.HvcX != nil {
177183
codec = "hevc"
184+
} else if stbl.Stsd.VvcX != nil {
185+
codec = "vvc"
178186
}
179187
nrSamples := stbl.Stsz.SampleNumber
180188
mdat := f.Mdat
@@ -194,9 +202,9 @@ func parseProgressiveMp4(w io.Writer, f *mp4.File, maxNrSamples int, codec strin
194202
}
195203
size := stbl.Stsz.GetSampleSize(sampleNr)
196204
decTime, _ := stbl.Stts.GetDecodeTime(uint32(sampleNr))
197-
var cto int32 = 0
205+
var cto int64 = 0
198206
if stbl.Ctts != nil {
199-
cto = stbl.Ctts.GetCompositionTimeOffset(uint32(sampleNr))
207+
cto = int64(stbl.Ctts.GetCompositionTimeOffset(uint32(sampleNr)))
200208
}
201209
// Next find sample bytes as slice in mdat
202210
offsetInMdatData := uint64(offset) - mdatPayloadStart
@@ -217,9 +225,11 @@ func parseProgressiveMp4(w io.Writer, f *mp4.File, maxNrSamples int, codec strin
217225
}
218226
}
219227
}
220-
err = printAVCNalus(w, avcSPS, nalus, sampleNr, decTime+uint64(cto), seiLevel, parameterSets, nrRaw)
228+
err = printAVCNalus(w, avcSPS, nalus, sampleNr, int64(decTime)+cto, seiLevel, parameterSets, nrRaw)
221229
case "hevc", "h.265", "h265":
222-
err = printHEVCNalus(w, nalus, sampleNr, decTime+uint64(cto), seiLevel, parameterSets, nrRaw)
230+
err = printHEVCNalus(w, nalus, sampleNr, int64(decTime)+cto, seiLevel, parameterSets, nrRaw)
231+
case "vvc", "h.266", "h266":
232+
err = printVVCNalus(w, nalus, sampleNr, int64(decTime)+cto, seiLevel, parameterSets, nrRaw)
223233
default:
224234
return fmt.Errorf("unknown codec: %s", codec)
225235
}
@@ -258,6 +268,7 @@ func parseFragmentedMp4(w io.Writer, f *mp4.File, maxNrSamples int, codec string
258268
var trex *mp4.TrexBox
259269
var avcSPS *avc.SPS
260270
var err error
271+
var editListOffset int64 = 0
261272
if f.Init != nil { // Auto-detect codec if moov box is there
262273
moov := f.Init.Moov
263274
videoTrak, ok := findFirstVideoTrak(moov)
@@ -275,8 +286,11 @@ func parseFragmentedMp4(w io.Writer, f *mp4.File, maxNrSamples int, codec string
275286
}
276287
} else if stbl.Stsd.HvcX != nil {
277288
codec = "hevc"
289+
} else if stbl.Stsd.VvcX != nil {
290+
codec = "vvc"
278291
}
279292
trex, _ = moov.Mvex.GetTrex(videoTrak.Tkhd.TrackID)
293+
editListOffset = getVideoListOffset(moov, videoTrak)
280294
}
281295
iSamples := make([]mp4.FullSample, 0)
282296
for _, iSeg := range f.Segments {
@@ -295,9 +309,11 @@ func parseFragmentedMp4(w io.Writer, f *mp4.File, maxNrSamples int, codec string
295309
}
296310
switch codec {
297311
case "avc", "h.264", "h264":
298-
err = printAVCNalus(w, avcSPS, nalus, i+1, s.PresentationTime(), seiLevel, parameterSets, nrRaw)
312+
err = printAVCNalus(w, avcSPS, nalus, i+1, s.PresentationTime()+editListOffset, seiLevel, parameterSets, nrRaw)
299313
case "hevc", "h.265", "h265":
300-
err = printHEVCNalus(w, nalus, i+1, s.PresentationTime(), seiLevel, parameterSets, nrRaw)
314+
err = printHEVCNalus(w, nalus, i+1, s.PresentationTime()+editListOffset, seiLevel, parameterSets, nrRaw)
315+
case "vvc", "h.266", "h266":
316+
err = printVVCNalus(w, nalus, i+1, s.PresentationTime()+editListOffset, seiLevel, parameterSets, nrRaw)
301317
default:
302318
return fmt.Errorf("unknown codec: %s", codec)
303319
}
@@ -312,7 +328,24 @@ func parseFragmentedMp4(w io.Writer, f *mp4.File, maxNrSamples int, codec string
312328
return nil
313329
}
314330

315-
func printAVCNalus(w io.Writer, avcSPS *avc.SPS, nalus [][]byte, nr int, pts uint64, seiLevel int, parameterSets bool, nrRaw int) error {
331+
func getVideoListOffset(moov *mp4.MoovBox, videoTrak *mp4.TrakBox) int64 {
332+
editListOffset := int64(0)
333+
for _, ch := range videoTrak.Children {
334+
if ch.Type() == "edts" {
335+
edts := ch.(*mp4.EdtsBox)
336+
for _, el := range edts.Elst {
337+
for _, entry := range el.Entries {
338+
if entry.MediaTime < 0 {
339+
editListOffset = int64(entry.SegmentDuration) * int64(videoTrak.Mdia.Mdhd.Timescale) / int64(moov.Mvhd.Timescale)
340+
}
341+
}
342+
}
343+
}
344+
}
345+
return editListOffset
346+
}
347+
348+
func printAVCNalus(w io.Writer, avcSPS *avc.SPS, nalus [][]byte, nr int, pts int64, seiLevel int, parameterSets bool, nrRaw int) error {
316349
msg := ""
317350
var seiNALUs [][]byte
318351
totLen := 0
@@ -363,7 +396,7 @@ func printAVCNalus(w io.Writer, avcSPS *avc.SPS, nalus [][]byte, nr int, pts uin
363396
return nil
364397
}
365398

366-
func printHEVCNalus(w io.Writer, nalus [][]byte, nr int, pts uint64, seiLevel int, parameterSets bool, nrRaw int) error {
399+
func printHEVCNalus(w io.Writer, nalus [][]byte, nr int, pts int64, seiLevel int, parameterSets bool, nrRaw int) error {
367400
msg := ""
368401
var seiNALUs [][]byte
369402
totLen := 0
@@ -401,6 +434,52 @@ func printHEVCNalus(w io.Writer, nalus [][]byte, nr int, pts uint64, seiLevel in
401434
return nil
402435
}
403436

437+
func printVVCNalus(w io.Writer, nalus [][]byte, nr int, pts int64, seiLevel int, parameterSets bool, nrRaw int) error {
438+
msg := ""
439+
var seiNALUs [][]byte
440+
totLen := 0
441+
for i, nalu := range nalus {
442+
totLen += 4 + len(nalu)
443+
if i > 0 {
444+
msg += ","
445+
}
446+
header, err := vvc.ParseNaluHeader(nalu)
447+
if err != nil {
448+
return fmt.Errorf("error parsing VVC NALU header: %w", err)
449+
}
450+
naluType := header.NaluType
451+
if nrRaw > 0 {
452+
msg += fmt.Sprintf("\n %s (%dB)", naluType, len(nalu))
453+
msg += fmt.Sprintf(" raw: %s", bytesToStringN(nalu, nrRaw))
454+
} else {
455+
msg += fmt.Sprintf(" %s (%dB)", naluType, len(nalu))
456+
}
457+
if seiLevel > 0 && (naluType == vvc.NALU_SEI_PREFIX || naluType == vvc.NALU_SEI_SUFFIX) {
458+
seiNALUs = append(seiNALUs, nalu)
459+
}
460+
}
461+
fmt.Fprintf(w, "Sample %d, pts=%d (%dB):%s\n", nr, pts, totLen, msg)
462+
printSEINALus(w, seiNALUs, "vvc", seiLevel, nil)
463+
if parameterSets {
464+
for _, nalu := range nalus {
465+
header, err := vvc.ParseNaluHeader(nalu)
466+
if err != nil {
467+
continue
468+
}
469+
naluType := header.NaluType
470+
switch naluType {
471+
case vvc.NALU_VPS:
472+
fmt.Fprintf(w, " VPS: %s\n", hex.EncodeToString(nalu))
473+
case vvc.NALU_SPS:
474+
fmt.Fprintf(w, " SPS: %s\n", hex.EncodeToString(nalu))
475+
case vvc.NALU_PPS:
476+
fmt.Fprintf(w, " PPS: %s\n", hex.EncodeToString(nalu))
477+
}
478+
}
479+
}
480+
return nil
481+
}
482+
404483
// printSEINALus - print interpreted information if seiLevel is >= 1. Add hex dump if seiLevel >= 2
405484
func printSEINALus(w io.Writer, seiNALUs [][]byte, codec string, seiLevel int, avcSPS *avc.SPS) {
406485
if seiLevel < 1 {
@@ -412,7 +491,7 @@ func printSEINALus(w io.Writer, seiNALUs [][]byte, codec string, seiLevel int, a
412491
case "avc":
413492
seiCodec = sei.AVC
414493
hdrLen = 1
415-
case "hevc":
494+
case "hevc", "vvc": // VVC uses same SEI format as HEVC
416495
seiCodec = sei.HEVC
417496
hdrLen = 2
418497
}
@@ -476,6 +555,8 @@ func findAnnexBFrames(nalus [][]byte, codec string) ([][][]byte, error) {
476555
isAUD = isAvcAudNalu
477556
case "hevc":
478557
isAUD = isHEVCAudNalu
558+
case "vvc":
559+
isAUD = isVVCAudNalu
479560
default:
480561
return nil, fmt.Errorf("unknown codec: %s", codec)
481562
}
@@ -502,3 +583,11 @@ func isAvcAudNalu(nalu []byte) bool {
502583
func isHEVCAudNalu(nalu []byte) bool {
503584
return hevc.GetNaluType(nalu[0]) == hevc.NALU_AUD
504585
}
586+
587+
func isVVCAudNalu(nalu []byte) bool {
588+
header, err := vvc.ParseNaluHeader(nalu)
589+
if err != nil {
590+
return false
591+
}
592+
return header.NaluType == vvc.NALU_AUD
593+
}

cmd/mp4ff-nallister/main_test.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import (
44
"bytes"
55
"os"
66
"testing"
7+
8+
"github.com/Eyevinn/mp4ff/avc"
9+
"github.com/Eyevinn/mp4ff/mp4"
710
)
811

912
func TestOptions(t *testing.T) {
@@ -28,7 +31,7 @@ func TestOptions(t *testing.T) {
2831
goldenOut: "testdata/golden_prot_h264_4pics.txt", expectedErr: false},
2932
{desc: "mp4H264", args: []string{appName, "testdata/h264.mp4"},
3033
goldenOut: "testdata/golden_h264_mp4.txt", expectedErr: false},
31-
{desc: "annexBHEVC", args: []string{appName, "-annexb", "-c", "hevc", "testdata/hevc.265"},
34+
{desc: "annexBHEVC", args: []string{appName, "-annexb", "-c", "hevc", "-ps", "testdata/hevc.265"},
3235
goldenOut: "testdata/golden_hevc_265.txt", expectedErr: false},
3336
{desc: "annexBHEVC with SEI", args: []string{appName, "-annexb", "-c", "hevc", "-sei", "2", "testdata/hevc.265"},
3437
goldenOut: "", expectedErr: false},
@@ -38,6 +41,10 @@ func TestOptions(t *testing.T) {
3841
goldenOut: "testdata/golden_h264_frag_raw.txt", expectedErr: false},
3942
{desc: "avcSeiTime", args: []string{appName, "-sei", "2", "-annexb", "testdata/4pics.264"},
4043
goldenOut: "testdata/golden_4pic_sei_264.txt", expectedErr: false},
44+
{desc: "vvc 2s", args: []string{appName, "../../mp4/testdata/vvc_400kbps_2s.mp4"}, expectedErr: false,
45+
goldenOut: "testdata/golden_vvc_2s.txt"},
46+
{desc: "vvc annexB", args: []string{appName, "-annexb", "-ps", "-c", "vvc", "testdata/annexb.vvc"}, expectedErr: false,
47+
goldenOut: "testdata/golden_vvc_annexb.txt"},
4148
{desc: "version", args: []string{appName, "-version"}, expectedErr: false},
4249
{desc: "help", args: []string{appName, "-h"}, expectedErr: false},
4350
}
@@ -75,3 +82,29 @@ func getExpected(t *testing.T, filename string) string {
7582
r := bytes.ReplaceAll(b, []byte("\r\n"), []byte("\n"))
7683
return string(r)
7784
}
85+
86+
func MakeByteStream(t *testing.T, inFile, outFile string) {
87+
t.Helper()
88+
ifd, err := os.Open(inFile)
89+
if err != nil {
90+
t.Fatalf("could not open file %s: %s", inFile, err)
91+
}
92+
d, err := mp4.DecodeFile(ifd)
93+
if err != nil {
94+
t.Fatalf("could not decode file %s: %s", inFile, err)
95+
}
96+
fullSamples, err := d.Segments[0].Fragments[0].GetFullSamples(nil)
97+
if err != nil {
98+
t.Fatalf("could not get full samples: %s", err)
99+
}
100+
byteStream := make([]byte, 0, 1024)
101+
for i := 0; i <= 5; i++ {
102+
fs := fullSamples[i]
103+
bs := avc.ConvertSampleToByteStream(fs.Data)
104+
byteStream = append(byteStream, bs...)
105+
}
106+
err = os.WriteFile(outFile, byteStream, 0644)
107+
if err != nil {
108+
t.Fatalf("could not write file %s: %s", outFile, err)
109+
}
110+
}
17.4 KB
Binary file not shown.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
Sample 1, pts=0 (14185B): VPS_32 (24B), SPS_33 (42B), PPS_34 (7B), SEI_39 (2340B), RAP_IDR_20 (914B), NonRAP_Trail_1 (266B), NonRAP_Trail_1 (160B), NonRAP_Trail_0 (151B), NonRAP_Trail_1 (276B), NonRAP_Trail_1 (192B), NonRAP_Trail_0 (212B), NonRAP_Trail_0 (183B), NonRAP_Trail_0 (190B), NonRAP_Trail_1 (353B), NonRAP_Trail_1 (178B), NonRAP_Trail_0 (177B), NonRAP_Trail_1 (258B), NonRAP_Trail_1 (184B), NonRAP_Trail_0 (171B), NonRAP_Trail_1 (227B), NonRAP_Trail_0 (176B), NonRAP_Trail_1 (220B), NonRAP_Trail_1 (267B), NonRAP_Trail_1 (224B), NonRAP_Trail_0 (200B), NonRAP_Trail_0 (200B), NonRAP_Trail_0 (198B), NonRAP_Trail_1 (228B), NonRAP_Trail_0 (191B), NonRAP_Trail_1 (288B), NonRAP_Trail_1 (326B), NonRAP_Trail_1 (212B), NonRAP_Trail_0 (214B), NonRAP_Trail_0 (201B), NonRAP_Trail_0 (209B), NonRAP_Trail_1 (298B), NonRAP_Trail_1 (202B), NonRAP_Trail_0 (194B), NonRAP_Trail_0 (191B), NonRAP_Trail_0 (200B), NonRAP_Trail_1 (328B), NonRAP_Trail_1 (204B), NonRAP_Trail_0 (201B), NonRAP_Trail_0 (199B), NonRAP_Trail_0 (205B), NonRAP_Trail_1 (222B), NonRAP_Trail_1 (194B), NonRAP_Trail_0 (177B), NonRAP_Trail_0 (187B), NonRAP_Trail_1 (331B), NonRAP_Trail_1 (211B), NonRAP_Trail_0 (180B), NonRAP_Trail_0 (197B), NonRAP_Trail_0 (189B)
2+
VPS: 40010c01ffff01600000030090000003000003007b959809
3+
SPS: 42010101600000030090000003000003007ba003c08010e596566924caf0169c20000003002000000641
4+
PPS: 4401c172b46240
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
Sample 1, pts=12288 (11051B): AUD_20 (3B), SPS_15 (176B), PPS_16 (13B), PREFIX_APS_17 (118B), IDR_W_RADL_7 (10721B)
2+
Sample 2, pts=7680 (2192B): AUD_20 (3B), PREFIX_APS_17 (62B), RADL_2 (2115B)
3+
Sample 3, pts=3584 (1846B): AUD_20 (3B), PREFIX_APS_17 (21B), RADL_2 (1810B)
4+
Sample 4, pts=1536 (1404B): AUD_20 (3B), PREFIX_APS_17 (41B), RADL_2 (1348B)
5+
Sample 5, pts=512 (683B): AUD_20 (3B), PREFIX_APS_17 (19B), RADL_2 (649B)
6+
Sample 6, pts=0 (655B): AUD_20 (3B), PREFIX_APS_17 (53B), RADL_2 (587B)
7+
Sample 7, pts=1024 (277B): AUD_20 (3B), PREFIX_APS_17 (8B), RADL_2 (254B)
8+
Sample 8, pts=2560 (453B): AUD_20 (3B), PREFIX_APS_17 (13B), RADL_2 (425B)
9+
Sample 9, pts=2048 (342B): AUD_20 (3B), RADL_2 (331B)
10+
Sample 10, pts=3072 (331B): AUD_20 (3B), RADL_2 (320B)
11+
Sample 11, pts=5632 (789B): AUD_20 (3B), PREFIX_APS_17 (38B), RADL_2 (736B)
12+
Sample 12, pts=4608 (437B): AUD_20 (3B), RADL_2 (426B)
13+
Sample 13, pts=4096 (273B): AUD_20 (3B), RADL_2 (262B)
14+
Sample 14, pts=5120 (263B): AUD_20 (3B), RADL_2 (252B)
15+
Sample 15, pts=6656 (404B): AUD_20 (3B), RADL_2 (393B)
16+
Sample 16, pts=6144 (257B): AUD_20 (3B), RADL_2 (246B)
17+
Sample 17, pts=7168 (281B): AUD_20 (3B), RADL_2 (270B)
18+
Sample 18, pts=11776 (822B): AUD_20 (3B), PREFIX_APS_17 (13B), RADL_2 (794B)
19+
Sample 19, pts=9728 (790B): AUD_20 (3B), PREFIX_APS_17 (36B), RADL_2 (739B)
20+
Sample 20, pts=8704 (443B): AUD_20 (3B), PREFIX_APS_17 (8B), RADL_2 (420B)
21+
Sample 21, pts=8192 (336B): AUD_20 (3B), RADL_2 (325B)
22+
Sample 22, pts=9216 (310B): AUD_20 (3B), RADL_2 (299B)
23+
Sample 23, pts=10752 (446B): AUD_20 (3B), RADL_2 (435B)
24+
Sample 24, pts=10240 (286B): AUD_20 (3B), RADL_2 (275B)
25+
Sample 25, pts=11264 (252B): AUD_20 (3B), RADL_2 (241B)
26+
Sample 26, pts=25088 (14691B): AUD_20 (3B), SPS_15 (176B), PPS_16 (13B), PREFIX_APS_17 (94B), IDR_W_RADL_7 (14385B)
27+
Sample 27, pts=20480 (4034B): AUD_20 (3B), PREFIX_APS_17 (69B), RADL_2 (3950B)
28+
Sample 28, pts=16384 (3323B): AUD_20 (3B), PREFIX_APS_17 (116B), RADL_2 (3192B)
29+
Sample 29, pts=14336 (2123B): AUD_20 (3B), PREFIX_APS_17 (63B), RADL_2 (2045B)
30+
Sample 30, pts=13312 (1158B): AUD_20 (3B), PREFIX_APS_17 (14B), RADL_2 (1129B)
31+
Sample 31, pts=12800 (610B): AUD_20 (3B), RADL_2 (599B)
32+
Sample 32, pts=13824 (361B): AUD_20 (3B), PREFIX_APS_17 (13B), RADL_2 (333B)
33+
Sample 33, pts=15360 (450B): AUD_20 (3B), PREFIX_APS_17 (15B), RADL_2 (420B)
34+
Sample 34, pts=14848 (385B): AUD_20 (3B), RADL_2 (374B)
35+
Sample 35, pts=15872 (313B): AUD_20 (3B), PREFIX_APS_17 (8B), RADL_2 (290B)
36+
Sample 36, pts=18432 (1241B): AUD_20 (3B), PREFIX_APS_17 (42B), RADL_2 (1184B)
37+
Sample 37, pts=17408 (613B): AUD_20 (3B), PREFIX_APS_17 (40B), RADL_2 (558B)
38+
Sample 38, pts=16896 (318B): AUD_20 (3B), RADL_2 (307B)
39+
Sample 39, pts=17920 (335B): AUD_20 (3B), RADL_2 (324B)
40+
Sample 40, pts=19456 (532B): AUD_20 (3B), PREFIX_APS_17 (10B), RADL_2 (507B)
41+
Sample 41, pts=18944 (334B): AUD_20 (3B), RADL_2 (323B)
42+
Sample 42, pts=19968 (342B): AUD_20 (3B), PREFIX_APS_17 (8B), RADL_2 (319B)
43+
Sample 43, pts=24576 (1461B): AUD_20 (3B), PREFIX_APS_17 (35B), RADL_2 (1411B)
44+
Sample 44, pts=22528 (1043B): AUD_20 (3B), PREFIX_APS_17 (50B), RADL_2 (978B)
45+
Sample 45, pts=21504 (459B): AUD_20 (3B), PREFIX_APS_17 (15B), RADL_2 (429B)
46+
Sample 46, pts=20992 (320B): AUD_20 (3B), RADL_2 (309B)
47+
Sample 47, pts=22016 (230B): AUD_20 (3B), RADL_2 (219B)
48+
Sample 48, pts=23552 (558B): AUD_20 (3B), PREFIX_APS_17 (14B), RADL_2 (529B)
49+
Sample 49, pts=23040 (341B): AUD_20 (3B), RADL_2 (330B)
50+
Sample 50, pts=24064 (336B): AUD_20 (3B), RADL_2 (325B)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Sample 1, pts=0 (11051B): AUD_20 (3B), SPS_15 (176B), PPS_16 (13B), PREFIX_APS_17 (118B), IDR_W_RADL_7 (10721B)
2+
SPS: 007900ad0233800000800a0200b446a007374dba6469149bce1365630408278034833610864c442064883521e8f56a4bc926a4b2445a88bc449a88914911264889351962210b24216a10bc217ab525e4bd43483362419b1012210202454204048d210202458810122208091641012242024c81222102459081224409341224824e12709b222211164222444d22493a7fe9765fe7240000030004000003006784ec0061a80004c4b40030d40002625a10
3+
PPS: 008100000501005a22241fb820
4+
Sample 2, pts=0 (2192B): AUD_20 (3B), PREFIX_APS_17 (62B), RADL_2 (2115B)
5+
Sample 3, pts=0 (1846B): AUD_20 (3B), PREFIX_APS_17 (21B), RADL_2 (1810B)
6+
Sample 4, pts=0 (1404B): AUD_20 (3B), PREFIX_APS_17 (41B), RADL_2 (1348B)
7+
Sample 5, pts=0 (683B): AUD_20 (3B), PREFIX_APS_17 (19B), RADL_2 (649B)
8+
Sample 6, pts=0 (655B): AUD_20 (3B), PREFIX_APS_17 (53B), RADL_2 (587B)

0 commit comments

Comments
 (0)