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

Major optimization 6x faster #40

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ Thumbs.db
.idea/
cover*
test
*.swp
56 changes: 56 additions & 0 deletions .golangci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"run": {
"tests": false,
"timeout": "5m"
},
"linters": {
"enable": [
"asciicheck",
"bodyclose",
"deadcode",
"depguard",
"dogsled",
"dupl",
"durationcheck",
"errcheck",
"errname",
"errorlint",
"exportloopref",
"forcetypeassert",
"funlen",
"gocognit",
"gocritic",
"gocyclo",
"godot",
"goerr113",
"gofumpt",
"goprintffuncname",
"gosimple",
"govet",
"ineffassign",
"lll",
"misspell",
"nakedret",
"nestif",
"noctx",
"nolintlint",
"revive",
"rowserrcheck",
"staticcheck",
"structcheck",
"testpackage",
"typecheck",
"unconvert",
"unparam",
"unused",
"varcheck",
"whitespace"
]
},
"linters-settings": {
"funlen": {},
"gocritic": {
"disabled-checks": ["commentFormatting"]
}
}
}
48 changes: 48 additions & 0 deletions binary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package astits

import (
"io"
"log"

"github.com/icza/bitio"
)

// WriterAndByteWriter An io.Writer and io.ByteWriter at the same time.
type WriterAndByteWriter interface {
io.Writer
io.ByteWriter
}

// ReaderAndByteReader An io.Reader and io.ByteReader at the same time.
type ReaderAndByteReader interface {
io.Reader
io.ByteReader
}

// WriteBinary .
func WriteBinary(w *bitio.Writer, str string) error {
for _, r := range str {
var err error

switch r {
case '1':
err = w.WriteBool(true)
case '0':
err = w.WriteBool(false)
default:
log.Fatalf("invalid rune: %v", r)
}

if err != nil {
return err
}
}
return nil
}

// TryReadFull .
func TryReadFull(r *bitio.CountReader, p []byte) {
if r.TryError == nil {
_, r.TryError = io.ReadFull(r, p)
}
}
137 changes: 137 additions & 0 deletions binary_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package astits

import (
"bytes"
"fmt"
"io"
"testing"

"github.com/icza/bitio"
"github.com/stretchr/testify/require"
)

func TestBitsWriter(t *testing.T) {
// TODO Need to test LittleEndian
bw := &bytes.Buffer{}
w := bitio.NewWriter(bw)

err := WriteBinary(w, "000000")
require.NoError(t, err)
require.Equal(t, 0, bw.Len())

err = w.WriteBool(false)
require.NoError(t, err)

err = w.WriteBool(true)
require.Equal(t, []byte{1}, bw.Bytes())

_, err = w.Write([]byte{2, 3})
require.NoError(t, err)
require.Equal(t, []byte{1, 2, 3}, bw.Bytes())

err = w.WriteBits(uint64(4), 8)
require.NoError(t, err)
require.Equal(t, []byte{1, 2, 3, 4}, bw.Bytes())

err = w.WriteBits(uint64(5), 16)
require.NoError(t, err)
require.Equal(t, []byte{1, 2, 3, 4, 0, 5}, bw.Bytes())

err = w.WriteBits(uint64(6), 32)
require.NoError(t, err)
require.Equal(t, []byte{1, 2, 3, 4, 0, 5, 0, 0, 0, 6}, bw.Bytes())

err = w.WriteBits(uint64(7), 64)
require.NoError(t, err)
require.Equal(t, []byte{1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7}, bw.Bytes())

bw.Reset()
err = w.WriteBits(uint64(4), 3)
require.NoError(t, err)

err = w.WriteBits(uint64(4096), 13)
require.NoError(t, err)
require.Equal(t, []byte{144, 0}, bw.Bytes())
}

// testLimitedWriter is an implementation of io.Writer
// with max write size limit to test error handling
type testLimitedWriter struct {
BytesLimit int
}

func (t *testLimitedWriter) Write(p []byte) (n int, err error) {
t.BytesLimit -= len(p)
if t.BytesLimit >= 0 {
return len(p), nil
}
return len(p) + t.BytesLimit, io.EOF
}

func (t *testLimitedWriter) WriteByte(c byte) error {
_, err := t.Write([]byte{c})
return err
}

func BenchmarkBitsWriter_Write(b *testing.B) {
benchmarks := []func(*bitio.Writer){
func(w *bitio.Writer) { WriteBinary(w, "000000") },
func(w *bitio.Writer) { w.WriteBool(false) },
func(w *bitio.Writer) { w.WriteBool(true) },
func(w *bitio.Writer) { w.Write([]byte{2, 3}) },
func(w *bitio.Writer) { w.WriteByte(uint8(4)) },
func(w *bitio.Writer) { w.WriteBits(uint64(5), 16) },
func(w *bitio.Writer) { w.WriteBits(uint64(6), 32) },
func(w *bitio.Writer) { w.WriteBits(uint64(7), 64) },
}

bw := &bytes.Buffer{}
bw.Grow(1024)
w := bitio.NewWriter(bw)

for i, bm := range benchmarks {
b.Run(fmt.Sprintf("%v", i), func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
bw.Reset()
bm(w)
}
})
}
}

func BenchmarkBitsWriter_WriteN(b *testing.B) {
type benchData func(w *bitio.Writer)
benchmarks := []benchData{}
var i uint8
for i = 1; i <= 8; i++ {
benchmarks = append(benchmarks,
func(w *bitio.Writer) { w.WriteBits(0xff, i) })
}
for i = 1; i <= 16; i++ {
benchmarks = append(benchmarks,
func(w *bitio.Writer) { w.WriteBits(0xffff, i) })
}
for i = 1; i <= 32; i++ {
benchmarks = append(benchmarks,
func(w *bitio.Writer) { w.WriteBits(0xffffffff, i) })
}
for i = 1; i <= 64; i++ {
benchmarks = append(benchmarks,
func(w *bitio.Writer) { w.WriteBits(0xffffffffffffffff, i) })
}

bw := &bytes.Buffer{}
bw.Grow(1024)
w := bitio.NewWriter(bw)

for i, bm := range benchmarks {
b.Run(fmt.Sprintf("%v", i), func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
bw.Reset()
bm(w)
}
})
}
}
10 changes: 5 additions & 5 deletions clock_reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@ import (
"time"
)

// ClockReference represents a clock reference
// Base is based on a 90 kHz clock and extension is based on a 27 MHz clock
// ClockReference represents a clock reference.
// Base is based on a 90 kHz clock and extension is based on a 27 MHz clock.
type ClockReference struct {
Base, Extension int64
}

// newClockReference builds a new clock reference
// newClockReference builds a new clock reference.
func newClockReference(base, extension int64) *ClockReference {
return &ClockReference{
Base: base,
Extension: extension,
}
}

// Duration converts the clock reference into duration
// Duration converts the clock reference into duration.
func (p ClockReference) Duration() time.Duration {
return time.Duration(p.Base*1e9/90000) + time.Duration(p.Extension*1e9/27000000)
}

// Time converts the clock reference into time
// Time converts the clock reference into time.
func (p ClockReference) Time() time.Time {
return time.Unix(0, p.Duration().Nanoseconds())
}
13 changes: 8 additions & 5 deletions cmd/astits-es-split/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package main
import (
"bufio"
"context"
"errors"
"flag"
"fmt"
"io"
"log"
"os"
"path"
Expand All @@ -23,7 +25,7 @@ type muxerOut struct {
w *bufio.Writer
}

func main() {
func main() { // nolint:funlen,gocognit,gocyclo
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Split TS file into multiple files each holding one elementary stream")
fmt.Fprintf(flag.CommandLine.Output(), "%s INPUT_FILE [FLAGS]:\n", os.Args[0])
Expand All @@ -41,7 +43,7 @@ func main() {

_, err = os.Stat(*outDir)
if !os.IsNotExist(err) {
log.Fatalf("can't write to `%s': already exists", *outDir)
log.Fatalf("can't write to `%s': already exists", *outDir) // nolint:gocritic
}

if err = os.MkdirAll(*outDir, os.ModePerm); err != nil {
Expand Down Expand Up @@ -69,7 +71,7 @@ func main() {
for {
d, err := demux.NextData()
if err != nil {
if err == astits.ErrNoMorePackets {
if errors.Is(err, io.EOF) {
break
}
log.Fatalf("%v", err)
Expand All @@ -81,7 +83,7 @@ func main() {
continue
}

if d.PMT != nil {
if d.PMT != nil { // nolint:nestif
pmts[d.PMT.ProgramNumber] = d.PMT

gotAllPMTs = true
Expand Down Expand Up @@ -191,7 +193,8 @@ func main() {
}

timeDiff := time.Since(timeStarted)
log.Printf("%d bytes written at rate %.02f mb/s", bytesWritten, (float64(bytesWritten)/1024.0/1024.0)/timeDiff.Seconds())
log.Printf("%d bytes written at rate %.02f mb/s", bytesWritten,
(float64(bytesWritten)/1024.0/1024.0)/timeDiff.Seconds())

for _, f := range outfiles {
if err = f.w.Flush(); err != nil {
Expand Down
Loading