From 5f259aa4107c0cc646c1f644bc0d86b070dbfc30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbjo=CC=88rn=20Einarsson?= Date: Mon, 15 Mar 2021 09:23:46 +0100 Subject: [PATCH 1/3] improve: three times faster bit write benchmark without allocation --- bits/bits.go | 14 +++++++++----- bits/bits_benchmark_test.go | 8 ++++++++ bits/ebsp_writer.go | 21 +++++++++++++-------- mp4/mediasegment_test.go | 13 +++++++++++++ 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/bits/bits.go b/bits/bits.go index fea22e27..86b56ce3 100644 --- a/bits/bits.go +++ b/bits/bits.go @@ -8,9 +8,10 @@ import ( // Writer writes bits into underlying io.Writer. Stops writing at first error. // Errors that have occured can later be checked with Error(). type Writer struct { - n int // current number of bits - v uint // current accumulated value - err error // The first error caused by any write operation + n int // current number of bits + v uint // current accumulated value + err error // The first error caused by any write operation + out []byte // Slice of length 1 to avoid allocation at output wr io.Writer } @@ -18,7 +19,8 @@ type Writer struct { // NewWriter - returns a new Writer func NewWriter(w io.Writer) *Writer { return &Writer{ - wr: w, + wr: w, + out: make([]byte, 1), } } @@ -32,7 +34,9 @@ func (w *Writer) Write(bits uint, n int) { w.n += n for w.n >= 8 { b := (w.v >> (uint(w.n) - 8)) & mask(8) - if err := binary.Write(w.wr, binary.BigEndian, uint8(b)); err != nil { + w.out[0] = uint8(b) + _, err := w.wr.Write(w.out) + if err != nil { w.err = err return } diff --git a/bits/bits_benchmark_test.go b/bits/bits_benchmark_test.go index a56616da..3214bc08 100644 --- a/bits/bits_benchmark_test.go +++ b/bits/bits_benchmark_test.go @@ -16,3 +16,11 @@ func BenchmarkWrite(b *testing.B) { b.Fatal(err) } } + +func BenchmarkEbspWrite(b *testing.B) { + writer := NewEBSPWriter(ioutil.Discard) + b.ResetTimer() + for i := 0; i < b.N; i++ { + writer.Write(0xff, 8) + } +} diff --git a/bits/ebsp_writer.go b/bits/ebsp_writer.go index 7b8dd79b..0fa3e0b2 100644 --- a/bits/ebsp_writer.go +++ b/bits/ebsp_writer.go @@ -1,7 +1,6 @@ package bits import ( - "encoding/binary" "io" ) @@ -10,10 +9,11 @@ import ( // Stops writing at first error. // Errors that have occured can later be checked with Error(). type EBSPWriter struct { - n int // current number of bits - v uint // current accumulated value - err error // The first error caused by any write operation - nr0 int // Number preceeding zero bytes + n int // current number of bits + v uint // current accumulated value + err error // The first error caused by any write operation + nr0 int // Number preceeding zero bytes + out []byte // Slice of length 1 to avoid allocation at output wr io.Writer } @@ -21,7 +21,8 @@ type EBSPWriter struct { // NewWriter - returns a new Writer func NewEBSPWriter(w io.Writer) *EBSPWriter { return &EBSPWriter{ - wr: w, + wr: w, + out: make([]byte, 1), } } @@ -36,13 +37,17 @@ func (w *EBSPWriter) Write(bits uint, n int) { for w.n >= 8 { b := (w.v >> (uint(w.n) - 8)) & mask(8) if w.nr0 == 2 && b <= 3 { - if err := binary.Write(w.wr, binary.BigEndian, uint8(3)); err != nil { + w.out[0] = 0x3 + _, err := w.wr.Write(w.out) + if err != nil { w.err = err return } w.nr0 = 0 } - if err := binary.Write(w.wr, binary.BigEndian, uint8(b)); err != nil { + w.out[0] = uint8(b) + _, err := w.wr.Write(w.out) + if err != nil { w.err = err return } diff --git a/mp4/mediasegment_test.go b/mp4/mediasegment_test.go index bc94ffec..1fcdda3d 100644 --- a/mp4/mediasegment_test.go +++ b/mp4/mediasegment_test.go @@ -197,3 +197,16 @@ func TestMoofEncrypted(t *testing.T) { t.Error(err) } } + +func BenchmarkDecodeEncode(b *testing.B) { + inFile := "testdata/1.m4s" + raw, _ := ioutil.ReadFile(inFile) + + for i := 0; i < b.N; i++ { + buf := bytes.NewBuffer(raw) + f, _ := DecodeFile(buf) + var bufInSeg bytes.Buffer + f.EncodeVerbatim = true + _ = f.Encode(&bufInSeg) + } +} From d05ff329dbd0da991508516276dbe9ca8ff7aa71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbjo=CC=88rn=20Einarsson?= Date: Wed, 17 Mar 2021 22:47:18 +0100 Subject: [PATCH 2/3] feat: add Makefile and retrievable versions to mp4 and all cmd programs --- Makefile | 11 +++++++++ cmd/mp4ff-fixtrex/main.go | 44 ++++++++++++++++++++++++++++++++++++ cmd/mp4ff-info/Makefile | 9 ++++++++ cmd/mp4ff-info/main.go | 7 ++++++ cmd/mp4ff-nallister/main.go | 6 +++++ cmd/mp4ff-pslister/main.go | 6 +++++ cmd/mp4ff-wvttlister/main.go | 6 +++++ mp4/version.go | 22 ++++++++++++++++++ 8 files changed, 111 insertions(+) create mode 100644 Makefile create mode 100644 cmd/mp4ff-fixtrex/main.go create mode 100644 cmd/mp4ff-info/Makefile create mode 100644 mp4/version.go diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..e8df1ba2 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +all: mp4ff-info mp4ff-nallister mp4ff-pslister mp4ff-wvttlister + +mp4ff-info mp4ff-nallister mp4ff-pslister mp4ff-wvttlister: + go build -ldflags "-X github.com/edgeware/mp4ff/mp4.commitVersion=$$(git describe --tags HEAD) -X github.com/edgeware/mp4ff/mp4.commitDate=$$(git log -1 --format=%ct)" -o out/$@ cmd/$@/main.go + +clean: + rm -f out/* + +install: all + cp out/* $(GOPATH)/bin/ + diff --git a/cmd/mp4ff-fixtrex/main.go b/cmd/mp4ff-fixtrex/main.go new file mode 100644 index 00000000..250df8a2 --- /dev/null +++ b/cmd/mp4ff-fixtrex/main.go @@ -0,0 +1,44 @@ +package main + +import ( + "flag" + "log" + "os" + + "github.com/edgeware/mp4ff/mp4" +) + +func main() { + + inFilePath := flag.String("i", "", "Required: Path to input mp4 file") + outFilePath := flag.String("o", "", "Required: Output filepath (without extension)") + flag.Parse() + + if *inFilePath == "" || *outFilePath == "" { + flag.Usage() + return + } + + ifd, err := os.Open(*inFilePath) + if err != nil { + log.Fatalln(err) + } + defer ifd.Close() + parsedMp4, err := mp4.DecodeFile(ifd) + if err != nil { + log.Fatal(err) + } + + parsedMp4.Init.Moov.Mvex.Trex.TrackID = 3 + + ofd, err := os.Create(*outFilePath) + if err != nil { + log.Fatal(err) + } + defer ofd.Close() + + err = parsedMp4.Encode(ofd) + if err != nil { + log.Fatal(err) + } +} diff --git a/cmd/mp4ff-info/Makefile b/cmd/mp4ff-info/Makefile new file mode 100644 index 00000000..493a30d4 --- /dev/null +++ b/cmd/mp4ff-info/Makefile @@ -0,0 +1,9 @@ +build: + go build -ldflags "-X github.com/edgeware/mp4ff/mp4.commitVersion=$$(git describe --tags HEAD) -X github.com/edgeware/mp4ff/mp4.commitDate=$$(git log -1 --format=%ct)" . + +install: + go install -ldflags "-X github.com/edgeware/mp4ff/mp4.commitVersion=$$(git describe --tags HEAD) -X github.com/edgeware/mp4ff/mp4.commitDate=$$(git log -1 --format=%ct)" . + +linux-build: + GOOS=linux GOARCH=amd64 go build -ldflags "-X main.commitVersion=$$(git describe --tags HEAD) -X main.commitDate=$$(git log -1 --format=%ct)" + diff --git a/cmd/mp4ff-info/main.go b/cmd/mp4ff-info/main.go index ce0f6320..2a42894e 100644 --- a/cmd/mp4ff-info/main.go +++ b/cmd/mp4ff-info/main.go @@ -18,6 +18,7 @@ For some boxes, more details are available by using -l with a comma-separated li all:1 - level 1 for all boxes trun:1 - level 1 only for trun box all:1,trun:0 - level 1 for all boxes but trun + ` var Usage = func() { @@ -31,9 +32,15 @@ var Usage = func() { func main() { specBoxLevels := flag.String("l", "", "level of details, e.g. all:1 or trun:1,subs:1") + version := flag.Bool("version", false, "Get mp4ff version") flag.Parse() + if *version { + fmt.Printf("mp4ff-info %s\n", mp4.GetVersion()) + os.Exit(0) + } + var inFilePath = flag.Arg(0) if inFilePath == "" { Usage() diff --git a/cmd/mp4ff-nallister/main.go b/cmd/mp4ff-nallister/main.go index 8e962156..72a3214b 100644 --- a/cmd/mp4ff-nallister/main.go +++ b/cmd/mp4ff-nallister/main.go @@ -31,9 +31,15 @@ var Usage = func() { func main() { maxNrSamples := flag.Int("m", -1, "Max nr of samples to parse") codec := flag.String("c", "avc", "Codec to parse (avc or hevc)") + version := flag.Bool("version", false, "Get mp4ff version") flag.Parse() + if *version { + fmt.Printf("mp4ff-nallister %s\n", mp4.GetVersion()) + os.Exit(0) + } + var inFilePath = flag.Arg(0) if inFilePath == "" { Usage() diff --git a/cmd/mp4ff-pslister/main.go b/cmd/mp4ff-pslister/main.go index a27de3c1..9d077a92 100644 --- a/cmd/mp4ff-pslister/main.go +++ b/cmd/mp4ff-pslister/main.go @@ -42,9 +42,15 @@ func main() { spsHex := flag.String("sps", "", "SPS in hex format") ppsHex := flag.String("pps", "", "PPS in hex format") codec := flag.String("c", "avc", "Codec to parse (avc or hevc or auto)") + version := flag.Bool("version", false, "Get mp4ff version") flag.Parse() + if *version { + fmt.Printf("mp4ff-pslister %s\n", mp4.GetVersion()) + os.Exit(0) + } + if *inFile == "" && *spsHex == "" { Usage("Must specify infile or sps") os.Exit(1) diff --git a/cmd/mp4ff-wvttlister/main.go b/cmd/mp4ff-wvttlister/main.go index f3f85a56..f6e58fd7 100644 --- a/cmd/mp4ff-wvttlister/main.go +++ b/cmd/mp4ff-wvttlister/main.go @@ -29,9 +29,15 @@ var Usage = func() { func main() { maxNrSamples := flag.Int("m", -1, "Max nr of samples to parse") trackID := flag.Int("t", 0, "trackID to extract (0 is unspecified)") + version := flag.Bool("version", false, "Get mp4ff version") flag.Parse() + if *version { + fmt.Printf("mp4ff-wvttlister %s\n", mp4.GetVersion()) + os.Exit(0) + } + var inFilePath = flag.Arg(0) if inFilePath == "" { Usage() diff --git a/mp4/version.go b/mp4/version.go new file mode 100644 index 00000000..8af5f75e --- /dev/null +++ b/mp4/version.go @@ -0,0 +1,22 @@ +package mp4 + +import ( + "fmt" + "strconv" + "time" +) + +var ( + commitVersion string + commitDate string +) + +// GetVersion - get version and also commitHash and commitDate if inserted +func GetVersion() string { + seconds, _ := strconv.Atoi(commitDate) + if commitDate != "" { + t := time.Unix(int64(seconds), 0) + return fmt.Sprintf("%s, date: %s", commitVersion, t.Format("2006-01-02")) + } + return commitVersion +} From 2d3ac5d911b2f6b008c8d600505a629373f2900f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbjo=CC=88rn=20Einarsson?= Date: Thu, 18 Mar 2021 21:51:50 +0100 Subject: [PATCH 3/3] doc: Version v0.21.0 --- Versions.md | 1 + mp4/version.go | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Versions.md b/Versions.md index c822877c..37c2e026 100644 --- a/Versions.md +++ b/Versions.md @@ -2,6 +2,7 @@ | Version | Highlight | | ------ | --------- | +| 0.21.0 | feat: version number in apps and mp4 package | | 0.20.0 | feat: mp4ff-pslister better for hex SPS input | | 0.19.0 | fix: trun optimization, feat: mfra-related boxes | | 0.18.0 | feat: new mp4ff-wvttlister tool and fuller HEVC support | diff --git a/mp4/version.go b/mp4/version.go index 8af5f75e..5e09cbbb 100644 --- a/mp4/version.go +++ b/mp4/version.go @@ -7,11 +7,11 @@ import ( ) var ( - commitVersion string - commitDate string + commitVersion string = "v0.21.0" // Updated when building using Makefile + commitDate string // commitDate in Epoch seconds (inserted from Makefile) ) -// GetVersion - get version and also commitHash and commitDate if inserted +// GetVersion - get version and also commitHash and commitDate if inserted via Makefile func GetVersion() string { seconds, _ := strconv.Atoi(commitDate) if commitDate != "" {