Skip to content

Commit

Permalink
feat: scte-2038 support
Browse files Browse the repository at this point in the history
  • Loading branch information
tobbee committed Feb 23, 2024
1 parent 1b2c5c3 commit 32b255c
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 31 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Nothing yet
### Added

- SMPTE-2038 data option to mp2ts-tools

## [0.2.1] - 2024-01-25

Expand Down
4 changes: 3 additions & 1 deletion cmd/mp2ts-nallister/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ import (

var usg = `Usage of %s:
%s generates a list of nalus with information about timestamps, rai, SEI etc.
%s generates a list of AVC/HEVC nalus with information about timestamps, rai, SEI etc.
It can further be used to generate a list of SMPTE-2038 data.
`

func parseOptions() internal.Options {
opts := internal.Options{ShowStreamInfo: true, ShowService: false, ShowPS: false, ShowNALU: true, ShowSEIDetails: false, ShowStatistics: true}
flag.IntVar(&opts.MaxNrPictures, "max", 0, "max nr pictures to parse")
flag.BoolVar(&opts.ShowSEIDetails, "sei", false, "print detailed sei message information")
flag.BoolVar(&opts.ShowSMPTE2038, "smpte2038", false, "print details about SMPTE-2038 data")
flag.BoolVar(&opts.Indent, "indent", false, "indent JSON output")
flag.BoolVar(&opts.Version, "version", false, "print version")

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.19

require (
github.com/Comcast/gots/v2 v2.2.1
github.com/Eyevinn/mp4ff v0.42.0
github.com/Eyevinn/mp4ff v0.42.1-0.20240221161741-c9bb3c122204
github.com/asticode/go-astits v1.13.0
github.com/stretchr/testify v1.8.4
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/Comcast/gots/v2 v2.2.1 h1:LU/SRg7p2KQqVkNqInV7I4MOQKAqvWQP/PSSLtygP2s=
github.com/Comcast/gots/v2 v2.2.1/go.mod h1:firJ11on3eUiGHAhbY5cZNqG0OqhQ1+nSZHfsEEzVVU=
github.com/Eyevinn/mp4ff v0.42.0 h1:I85b/EDTkP77GsoBL8nRV6sfFKZhAXoP6oJHU8fv6kM=
github.com/Eyevinn/mp4ff v0.42.0/go.mod h1:w/6GSa5ghZ1VavzJK6McQ2/flx8mKtcrKDr11SsEweA=
github.com/Eyevinn/mp4ff v0.42.1-0.20240221161741-c9bb3c122204 h1:hxaiwOKm+ooV4lH/UIfgBzi8/CGj3pRIYXnVU3uQQpc=
github.com/Eyevinn/mp4ff v0.42.1-0.20240221161741-c9bb3c122204/go.mod h1:w/6GSa5ghZ1VavzJK6McQ2/flx8mKtcrKDr11SsEweA=
github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
github.com/asticode/go-astikit v0.42.0 h1:pnir/2KLUSr0527Tv908iAH6EGYYrYta132vvjXsH5w=
github.com/asticode/go-astikit v0.42.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
Expand Down
3 changes: 3 additions & 0 deletions internal/avc.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ func ParseAVCPES(jp *JsonPrinter, d *astits.DemuxerData, ps *AvcPS, o Options) (
})
}

if jp == nil {
return ps, nil
}
if firstPS {
for nr := range ps.spss {
jp.PrintPS(pid, "SPS", nr, ps.spsnalu, ps.spss[nr], o.VerbosePSInfo, o.ShowPS)
Expand Down
3 changes: 3 additions & 0 deletions internal/hevc.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ func ParseHEVCPES(jp *JsonPrinter, d *astits.DemuxerData, ps *HevcPS, o Options)
Data: nil,
})
}
if jp == nil {
return ps, nil
}

if firstPS {
jp.PrintPS(pid, "VPS", 0, ps.vpsnalu, nil, o.VerbosePSInfo, o.ShowPS)
Expand Down
19 changes: 6 additions & 13 deletions internal/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,9 @@ dataLoop:
if pmtPID < 0 && d.PMT != nil {
// Loop through elementary streams
for _, es := range d.PMT.ElementaryStreams {
var streamInfo *ElementaryStreamInfo
switch es.StreamType {
case astits.StreamTypeH264Video:
streamInfo = &ElementaryStreamInfo{PID: es.ElementaryPID, Codec: "AVC", Type: "video"}
esKinds[es.ElementaryPID] = "AVC"
case astits.StreamTypeAACAudio:
streamInfo = &ElementaryStreamInfo{PID: es.ElementaryPID, Codec: "AAC", Type: "audio"}
esKinds[es.ElementaryPID] = "AAC"
case astits.StreamTypeH265Video:
streamInfo = &ElementaryStreamInfo{PID: es.ElementaryPID, Codec: "HEVC", Type: "video"}
esKinds[es.ElementaryPID] = "HEVC"
}

streamInfo := ParseAstitsElementaryStreamInfo(es)
if streamInfo != nil {
esKinds[es.ElementaryPID] = streamInfo.Codec
jp.Print(streamInfo, o.ShowStreamInfo)
}
}
Expand Down Expand Up @@ -107,6 +96,10 @@ dataLoop:
}
nrPics++
statistics[d.PID] = &hevcPS.Statistics
case "SMPTE-2038":
if o.ShowSMPTE2038 {
ParseSMPTE2038(jp, d, o)

Check failure on line 101 in internal/parser.go

View workflow job for this annotation

GitHub Actions / build (macos-latest, 1.19)

undefined: ParseSMPTE2038

Check failure on line 101 in internal/parser.go

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 1.19)

undefined: ParseSMPTE2038
}
default:
// Skip unknown elementary streams
continue
Expand Down
2 changes: 1 addition & 1 deletion internal/testdata/golden_bbb_1s.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{"pid":257,"codec":"AAC","type":"audio"}
{"pid":256,"parameterSet":"SPS","nr":0,"hex":"6764001facd9405005bb011000000300100000030300f1831960","length":26}
{"pid":256,"parameterSet":"PPS","nr":0,"hex":"68ebecb22c","length":5}
{"pid":256,"rai":true,"pts":133500,"dts":126000,"imgType":"[I]","nalus":[{"type":"AUD_9","len":2},{"type":"SEI_6","len":701,"data":[{"msg":"SEIUserDataUnregisteredType (5)","payload":{"UUID":"3EXpvebZSLeWLNgg2SPu7w=="}}]},{"type":"SPS_7","len":26},{"type":"PPS_8","len":5},{"type":"IDR_5","len":209}]}
{"pid":256,"rai":true,"pts":133500,"dts":126000,"imgType":"[I]","nalus":[{"type":"AUD_9","len":2},{"type":"SEI_6","len":701,"data":[{"msg":"SEIUserDataUnregisteredType (5)"}]},{"type":"SPS_7","len":26},{"type":"PPS_8","len":5},{"type":"IDR_5","len":209}]}
{"pid":256,"rai":false,"pts":144750,"dts":129750,"imgType":"[P]","nalus":[{"type":"AUD_9","len":2},{"type":"NonIDR_1","len":34}]}
{"pid":256,"rai":false,"pts":137250,"dts":133500,"imgType":"[B]","nalus":[{"type":"AUD_9","len":2},{"type":"NonIDR_1","len":32}]}
{"pid":256,"rai":false,"pts":141000,"dts":137250,"imgType":"[B]","nalus":[{"type":"AUD_9","len":2},{"type":"NonIDR_1","len":32}]}
Expand Down
5 changes: 1 addition & 4 deletions internal/testdata/golden_bbb_1s_indented.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@
"len": 701,
"data": [
{
"msg": "SEIUserDataUnregisteredType (5)",
"payload": {
"UUID": "3EXpvebZSLeWLNgg2SPu7w=="
}
"msg": "SEIUserDataUnregisteredType (5)"
}
]
},
Expand Down
2 changes: 1 addition & 1 deletion internal/testdata/golden_obs_hevc_aac.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{"pid":256,"parameterSet":"VPS","nr":0,"hex":"40010c01ffff016000000300b00000030000030078170240","length":24}
{"pid":256,"parameterSet":"SPS","nr":0,"hex":"420101016000000300b00000030000030078a005020171f2e205ee45914bff2e7f13fa9a8080808040","length":41}
{"pid":256,"parameterSet":"PPS","nr":0,"hex":"4401c072f05324","length":7}
{"pid":256,"rai":true,"pts":1920,"dts":1920,"nalus":[{"type":"AUD_35","len":3},{"type":"VPS_32","len":24},{"type":"SPS_33","len":41},{"type":"PPS_34","len":7},{"type":"SEI_39","len":31,"data":[{"msg":"SEIUserDataUnregisteredType (5)"}]},{"type":"RAP_IDR_20","len":12860}]}
{"pid":256,"rai":true,"pts":1920,"dts":1920,"nalus":[{"type":"AUD_35","len":3},{"type":"VPS_32","len":24},{"type":"SPS_33","len":41},{"type":"PPS_34","len":7},{"type":"SEI_39","len":31},{"type":"RAP_IDR_20","len":12860}]}
{"pid":256,"rai":false,"pts":4920,"dts":4920,"nalus":[{"type":"AUD_35","len":3},{"type":"NonRAP_Trail_1","len":409}]}
{"pid":256,"rai":false,"pts":7920,"dts":7920,"nalus":[{"type":"AUD_35","len":3},{"type":"NonRAP_Trail_1","len":332}]}
{"pid":256,"rai":false,"pts":10920,"dts":10920,"nalus":[{"type":"AUD_35","len":3},{"type":"NonRAP_Trail_1","len":427}]}
Expand Down
7 changes: 1 addition & 6 deletions internal/testdata/golden_obs_hevc_aac_indented.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,7 @@
},
{
"type": "SEI_39",
"len": 31,
"data": [
{
"msg": "SEIUserDataUnregisteredType (5)"
}
]
"len": 31
},
{
"type": "RAP_IDR_20",
Expand Down
39 changes: 38 additions & 1 deletion internal/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package internal

import (
"context"
"encoding/hex"
"errors"
"flag"
"fmt"
Expand Down Expand Up @@ -30,6 +31,7 @@ type Options struct {
VerbosePSInfo bool
ShowNALU bool
ShowSEIDetails bool
ShowSMPTE2038 bool
ShowSCTE35 bool
ShowStatistics bool
FilterPids bool
Expand All @@ -38,9 +40,14 @@ type Options struct {
}

func CreateFullOptions(max int) Options {
return Options{MaxNrPictures: max, ShowStreamInfo: true, ShowService: true, ShowPS: true, ShowNALU: true, ShowSEIDetails: true, ShowStatistics: true}
return Options{MaxNrPictures: max, ShowStreamInfo: true, ShowService: true, ShowPS: true, ShowNALU: true, ShowSEIDetails: true, ShowSMPTE2038: true, ShowStatistics: true}
}

const (
ANC_REGISTERED_IDENTIFIER = 0x56414E43
ANC_DESCRIPTOR_TAG = 0xC4
)

type OptionParseFunc func() Options
type RunableFunc func(ctx context.Context, w io.Writer, f io.Reader, o Options) error

Expand Down Expand Up @@ -127,6 +134,36 @@ func ParseAstitsElementaryStreamInfo(es *astits.PMTElementaryStream) *Elementary
streamInfo = &ElementaryStreamInfo{PID: es.ElementaryPID, Codec: "HEVC", Type: "video"}
case astits.StreamTypeSCTE35:
streamInfo = &ElementaryStreamInfo{PID: es.ElementaryPID, Codec: "SCTE35", Type: "cue"}
case astits.StreamTypePrivateData:
streamInfo = &ElementaryStreamInfo{PID: es.ElementaryPID, Codec: "PrivateData", Type: "data"}
default:
return nil
}
for _, d := range es.ElementaryStreamDescriptors {
switch d.Tag {
case astits.DescriptorTagISO639LanguageAndAudioType:
l := d.ISO639LanguageAndAudioType
fmt.Printf("Language: %s\n", l.Language)
case astits.DescriptorTagDataStreamAlignment:
a := d.DataStreamAlignment
log.Printf("PID %d: Descriptor Data stream alignment: %d\n", es.ElementaryPID, a.Type)
case astits.DescriptorTagRegistration:
r := d.Registration
switch r.FormatIdentifier {
case ANC_REGISTERED_IDENTIFIER:
streamInfo.Codec = "SMPTE-2038"
streamInfo.Type = "ANC"
}
case ANC_DESCRIPTOR_TAG:
if streamInfo.Type != "ANC" {
log.Printf("PID %d: bad combination of descriptor 0xc4 and no preceding ANC", es.ElementaryPID)
continue
}
u := d.UserDefined
log.Printf("PID %d: Got ancillary descriptor with data: %q\n", es.ElementaryPID, hex.EncodeToString(u))
default:
// Nothing
}
}

return streamInfo
Expand Down

0 comments on commit 32b255c

Please sign in to comment.