From 577d6f3a284a1c5c7e9b7993c1050aa0d4006e5c Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:06:12 +0200 Subject: [PATCH] use mediacommon/pkg/mpegts in examples --- .../{mpegtsmuxer.go => mpegts_muxer.go} | 68 +++++--------- .../mpegts_muxer.go | 68 ++++++++++++++ .../mpegtsmuxer.go | 91 ------------------- .../{mpegtsmuxer.go => mpegts_muxer.go} | 80 ++++++---------- go.mod | 2 +- 5 files changed, 117 insertions(+), 192 deletions(-) rename examples/client-read-format-h264-save-to-disk/{mpegtsmuxer.go => mpegts_muxer.go} (66%) create mode 100644 examples/client-read-format-mpeg4audio-save-to-disk/mpegts_muxer.go delete mode 100644 examples/client-read-format-mpeg4audio-save-to-disk/mpegtsmuxer.go rename examples/server-h264-save-to-disk/{mpegtsmuxer.go => mpegts_muxer.go} (58%) diff --git a/examples/client-read-format-h264-save-to-disk/mpegtsmuxer.go b/examples/client-read-format-h264-save-to-disk/mpegts_muxer.go similarity index 66% rename from examples/client-read-format-h264-save-to-disk/mpegtsmuxer.go rename to examples/client-read-format-h264-save-to-disk/mpegts_muxer.go index 91a45c18..76d1a7e6 100644 --- a/examples/client-read-format-h264-save-to-disk/mpegtsmuxer.go +++ b/examples/client-read-format-h264-save-to-disk/mpegts_muxer.go @@ -2,15 +2,18 @@ package main import ( "bufio" - "context" "log" "os" "time" - "github.com/asticode/go-astits" "github.com/bluenviron/mediacommon/pkg/codecs/h264" + "github.com/bluenviron/mediacommon/pkg/formats/mpegts" ) +func durationGoToMPEGTS(v time.Duration) int64 { + return int64(v.Seconds() * 90000) +} + // mpegtsMuxer allows to save a H264 stream into a MPEG-TS file. type mpegtsMuxer struct { sps []byte @@ -18,7 +21,8 @@ type mpegtsMuxer struct { f *os.File b *bufio.Writer - mux *astits.Muxer + w *mpegts.Writer + track *mpegts.Track dtsExtractor *h264.DTSExtractor firstIDRReceived bool startDTS time.Duration @@ -32,19 +36,20 @@ func newMPEGTSMuxer(sps []byte, pps []byte) (*mpegtsMuxer, error) { } b := bufio.NewWriter(f) - mux := astits.NewMuxer(context.Background(), b) - mux.AddElementaryStream(astits.PMTElementaryStream{ - ElementaryPID: 256, - StreamType: astits.StreamTypeH264Video, - }) - mux.SetPCRPID(256) + track := &mpegts.Track{ + PID: 256, + Codec: &mpegts.CodecH264{}, + } + + w := mpegts.NewWriter(b, []*mpegts.Track{track}) return &mpegtsMuxer{ - sps: sps, - pps: pps, - f: f, - b: b, - mux: mux, + sps: sps, + pps: pps, + f: f, + b: b, + w: w, + track: track, }, nil } @@ -131,39 +136,8 @@ func (e *mpegtsMuxer) encode(au [][]byte, pts time.Duration) error { pts -= e.startDTS } - oh := &astits.PESOptionalHeader{ - MarkerBits: 2, - } - - if dts == pts { - oh.PTSDTSIndicator = astits.PTSDTSIndicatorOnlyPTS - oh.PTS = &astits.ClockReference{Base: int64(pts.Seconds() * 90000)} - } else { - oh.PTSDTSIndicator = astits.PTSDTSIndicatorBothPresent - oh.DTS = &astits.ClockReference{Base: int64(dts.Seconds() * 90000)} - oh.PTS = &astits.ClockReference{Base: int64(pts.Seconds() * 90000)} - } - - // encode into Annex-B - annexb, err := h264.AnnexBMarshal(au) - if err != nil { - return err - } - - // write TS packet - _, err = e.mux.WriteData(&astits.MuxerData{ - PID: 256, - AdaptationField: &astits.PacketAdaptationField{ - RandomAccessIndicator: idrPresent, - }, - PES: &astits.PESData{ - Header: &astits.PESHeader{ - OptionalHeader: oh, - StreamID: 224, // video - }, - Data: annexb, - }, - }) + // encode into MPEG-TS + err := e.w.WriteH26x(e.track, durationGoToMPEGTS(pts), durationGoToMPEGTS(dts), idrPresent, au) if err != nil { return err } diff --git a/examples/client-read-format-mpeg4audio-save-to-disk/mpegts_muxer.go b/examples/client-read-format-mpeg4audio-save-to-disk/mpegts_muxer.go new file mode 100644 index 00000000..82b866b7 --- /dev/null +++ b/examples/client-read-format-mpeg4audio-save-to-disk/mpegts_muxer.go @@ -0,0 +1,68 @@ +package main + +import ( + "bufio" + "log" + "os" + "time" + + "github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio" + "github.com/bluenviron/mediacommon/pkg/formats/mpegts" +) + +func durationGoToMPEGTS(v time.Duration) int64 { + return int64(v.Seconds() * 90000) +} + +// mpegtsMuxer allows to save a MPEG4-audio stream into a MPEG-TS file. +type mpegtsMuxer struct { + config *mpeg4audio.Config + f *os.File + b *bufio.Writer + w *mpegts.Writer + track *mpegts.Track +} + +// newMPEGTSMuxer allocates a mpegtsMuxer. +func newMPEGTSMuxer(config *mpeg4audio.Config) (*mpegtsMuxer, error) { + f, err := os.Create("mystream.ts") + if err != nil { + return nil, err + } + b := bufio.NewWriter(f) + + track := &mpegts.Track{ + PID: 256, + Codec: &mpegts.CodecMPEG4Audio{ + Config: *config, + }, + } + + w := mpegts.NewWriter(b, []*mpegts.Track{track}) + + return &mpegtsMuxer{ + config: config, + f: f, + b: b, + w: w, + track: track, + }, nil +} + +// close closes all the mpegtsMuxer resources. +func (e *mpegtsMuxer) close() { + e.b.Flush() + e.f.Close() +} + +// encode encodes a MPEG4-audio access unit into MPEG-TS. +func (e *mpegtsMuxer) encode(au []byte, pts time.Duration) error { + // encode into MPEG-TS + err := e.w.WriteMPEG4Audio(e.track, durationGoToMPEGTS(pts), [][]byte{au}) + if err != nil { + return err + } + + log.Println("wrote TS packet") + return nil +} diff --git a/examples/client-read-format-mpeg4audio-save-to-disk/mpegtsmuxer.go b/examples/client-read-format-mpeg4audio-save-to-disk/mpegtsmuxer.go deleted file mode 100644 index a9339536..00000000 --- a/examples/client-read-format-mpeg4audio-save-to-disk/mpegtsmuxer.go +++ /dev/null @@ -1,91 +0,0 @@ -package main - -import ( - "bufio" - "context" - "log" - "os" - "time" - - "github.com/asticode/go-astits" - "github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio" -) - -// mpegtsMuxer allows to save a MPEG4-audio stream into a MPEG-TS file. -type mpegtsMuxer struct { - config *mpeg4audio.Config - f *os.File - b *bufio.Writer - mux *astits.Muxer -} - -// newMPEGTSMuxer allocates a mpegtsMuxer. -func newMPEGTSMuxer(config *mpeg4audio.Config) (*mpegtsMuxer, error) { - f, err := os.Create("mystream.ts") - if err != nil { - return nil, err - } - b := bufio.NewWriter(f) - - mux := astits.NewMuxer(context.Background(), b) - mux.AddElementaryStream(astits.PMTElementaryStream{ - ElementaryPID: 257, - StreamType: astits.StreamTypeAACAudio, - }) - mux.SetPCRPID(257) - - return &mpegtsMuxer{ - config: config, - f: f, - b: b, - mux: mux, - }, nil -} - -// close closes all the mpegtsMuxer resources. -func (e *mpegtsMuxer) close() { - e.b.Flush() - e.f.Close() -} - -// encode encodes a MPEG4-audio access unit into MPEG-TS. -func (e *mpegtsMuxer) encode(au []byte, pts time.Duration) error { - // wrap access unit inside an ADTS packet - pkts := mpeg4audio.ADTSPackets{ - { - Type: e.config.Type, - SampleRate: e.config.SampleRate, - ChannelCount: e.config.ChannelCount, - AU: au, - }, - } - enc, err := pkts.Marshal() - if err != nil { - return err - } - - _, err = e.mux.WriteData(&astits.MuxerData{ - PID: 257, - AdaptationField: &astits.PacketAdaptationField{ - RandomAccessIndicator: true, - }, - PES: &astits.PESData{ - Header: &astits.PESHeader{ - OptionalHeader: &astits.PESOptionalHeader{ - MarkerBits: 2, - PTSDTSIndicator: astits.PTSDTSIndicatorOnlyPTS, - PTS: &astits.ClockReference{Base: int64(pts.Seconds() * 90000)}, - }, - PacketLength: uint16(len(enc) + 8), - StreamID: 192, // audio - }, - Data: enc, - }, - }) - if err != nil { - return err - } - - log.Println("wrote TS packet") - return nil -} diff --git a/examples/server-h264-save-to-disk/mpegtsmuxer.go b/examples/server-h264-save-to-disk/mpegts_muxer.go similarity index 58% rename from examples/server-h264-save-to-disk/mpegtsmuxer.go rename to examples/server-h264-save-to-disk/mpegts_muxer.go index 3fd5a965..83468611 100644 --- a/examples/server-h264-save-to-disk/mpegtsmuxer.go +++ b/examples/server-h264-save-to-disk/mpegts_muxer.go @@ -2,15 +2,18 @@ package main import ( "bufio" - "context" "log" "os" "time" - "github.com/asticode/go-astits" "github.com/bluenviron/mediacommon/pkg/codecs/h264" + "github.com/bluenviron/mediacommon/pkg/formats/mpegts" ) +func durationGoToMPEGTS(v time.Duration) int64 { + return int64(v.Seconds() * 90000) +} + // mpegtsMuxer allows to save a H264 stream into a MPEG-TS file. type mpegtsMuxer struct { sps []byte @@ -18,7 +21,8 @@ type mpegtsMuxer struct { f *os.File b *bufio.Writer - mux *astits.Muxer + w *mpegts.Writer + track *mpegts.Track dtsExtractor *h264.DTSExtractor firstIDRReceived bool startDTS time.Duration @@ -32,19 +36,20 @@ func newMPEGTSMuxer(sps []byte, pps []byte) (*mpegtsMuxer, error) { } b := bufio.NewWriter(f) - mux := astits.NewMuxer(context.Background(), b) - mux.AddElementaryStream(astits.PMTElementaryStream{ - ElementaryPID: 256, - StreamType: astits.StreamTypeH264Video, - }) - mux.SetPCRPID(256) + track := &mpegts.Track{ + PID: 256, + Codec: &mpegts.CodecH264{}, + } + + w := mpegts.NewWriter(b, []*mpegts.Track{track}) return &mpegtsMuxer{ - sps: sps, - pps: pps, - f: f, - b: b, - mux: mux, + sps: sps, + pps: pps, + f: f, + b: b, + w: w, + track: track, }, nil } @@ -55,7 +60,7 @@ func (e *mpegtsMuxer) close() { } // encode encodes H264 NALUs into MPEG-TS. -func (e *mpegtsMuxer) encode(nalus [][]byte, pts time.Duration) error { +func (e *mpegtsMuxer) encode(au [][]byte, pts time.Duration) error { // prepend an AUD. This is required by some players filteredNALUs := [][]byte{ {byte(h264.NALUTypeAccessUnitDelimiter), 240}, @@ -64,7 +69,7 @@ func (e *mpegtsMuxer) encode(nalus [][]byte, pts time.Duration) error { nonIDRPresent := false idrPresent := false - for _, nalu := range nalus { + for _, nalu := range au { typ := h264.NALUType(nalu[0] & 0x1F) switch typ { case h264.NALUTypeSPS: @@ -88,7 +93,7 @@ func (e *mpegtsMuxer) encode(nalus [][]byte, pts time.Duration) error { filteredNALUs = append(filteredNALUs, nalu) } - nalus = filteredNALUs + au = filteredNALUs if !nonIDRPresent && !idrPresent { return nil @@ -96,7 +101,7 @@ func (e *mpegtsMuxer) encode(nalus [][]byte, pts time.Duration) error { // add SPS and PPS before every group that contains an IDR if idrPresent { - nalus = append([][]byte{e.sps, e.pps}, nalus...) + au = append([][]byte{e.sps, e.pps}, au...) } var dts time.Duration @@ -111,7 +116,7 @@ func (e *mpegtsMuxer) encode(nalus [][]byte, pts time.Duration) error { e.dtsExtractor = h264.NewDTSExtractor() var err error - dts, err = e.dtsExtractor.Extract(nalus, pts) + dts, err = e.dtsExtractor.Extract(au, pts) if err != nil { return err } @@ -122,7 +127,7 @@ func (e *mpegtsMuxer) encode(nalus [][]byte, pts time.Duration) error { } else { var err error - dts, err = e.dtsExtractor.Extract(nalus, pts) + dts, err = e.dtsExtractor.Extract(au, pts) if err != nil { return err } @@ -131,39 +136,8 @@ func (e *mpegtsMuxer) encode(nalus [][]byte, pts time.Duration) error { pts -= e.startDTS } - oh := &astits.PESOptionalHeader{ - MarkerBits: 2, - } - - if dts == pts { - oh.PTSDTSIndicator = astits.PTSDTSIndicatorOnlyPTS - oh.PTS = &astits.ClockReference{Base: int64(pts.Seconds() * 90000)} - } else { - oh.PTSDTSIndicator = astits.PTSDTSIndicatorBothPresent - oh.DTS = &astits.ClockReference{Base: int64(dts.Seconds() * 90000)} - oh.PTS = &astits.ClockReference{Base: int64(pts.Seconds() * 90000)} - } - - // encode into Annex-B - annexb, err := h264.AnnexBMarshal(nalus) - if err != nil { - return err - } - - // write TS packet - _, err = e.mux.WriteData(&astits.MuxerData{ - PID: 256, - AdaptationField: &astits.PacketAdaptationField{ - RandomAccessIndicator: idrPresent, - }, - PES: &astits.PESData{ - Header: &astits.PESHeader{ - OptionalHeader: oh, - StreamID: 224, // video - }, - Data: annexb, - }, - }) + // encode into MPEG-TS + err := e.w.WriteH26x(e.track, durationGoToMPEGTS(pts), durationGoToMPEGTS(dts), idrPresent, au) if err != nil { return err } diff --git a/go.mod b/go.mod index c1afbb5f..f2ea3089 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/bluenviron/gortsplib/v3 go 1.18 require ( - github.com/asticode/go-astits v1.11.1-0.20230727094110-0df190a2dd87 github.com/bluenviron/mediacommon v0.7.1-0.20230730144331-10b74a4f6eda github.com/google/uuid v1.3.0 github.com/pion/rtcp v1.2.10 @@ -15,6 +14,7 @@ require ( require ( github.com/asticode/go-astikit v0.30.0 // indirect + github.com/asticode/go-astits v1.11.1-0.20230727094110-0df190a2dd87 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/pion/randutil v0.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect