Skip to content

Commit

Permalink
Merge pull request #5 from abema/change-option-name
Browse files Browse the repository at this point in the history
fix: PreferDF -> ForceAsNDF
lomavkin authored Jul 16, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents d8dea53 + 485d412 commit 664f824
Showing 2 changed files with 143 additions and 146 deletions.
94 changes: 49 additions & 45 deletions timecode/timecode.go
Original file line number Diff line number Diff line change
@@ -56,14 +56,14 @@ var (

// Timecode represents timecode.
type Timecode struct {
preferDF bool
sep string
lastSep string
r *rate
HH uint64
MM uint64
SS uint64
FF uint64
forceAsNDF bool
sep string
lastSep string
r *rate
HH uint64
MM uint64
SS uint64
FF uint64
}

// newNDFRate returns new NDF rate.
@@ -89,18 +89,22 @@ func newDFRate(num, den int32) (*rate, error) {
}

// newRate returns new rate.
func newRate(num, den int32, preferDF bool) (*rate, error) {
if preferDF {
r, err := newDFRate(num, den)
if err != nil {
if errors.Is(err, ErrUnsupportedFrameRate) {
return newNDFRate(num, den)
}
return nil, err
func newRate(num, den int32, forceAsNDF bool) (*rate, error) {
ndf, err := newNDFRate(num, den)
if err != nil {
return nil, err
}
if forceAsNDF {
return ndf, err
}
df, err := newDFRate(num, den)
if err != nil {
if errors.Is(err, ErrUnsupportedFrameRate) {
return ndf, nil
}
return r, nil
return nil, err
}
return newNDFRate(num, den)
return df, nil
}

// IsSupportedFrameRate returns whether frame rate is supported.
@@ -111,7 +115,7 @@ func IsSupportedFrameRate(num, den int32) bool {

// IsRepresentableFramesOptionParam represents IsRepresentableFrames option parameter.
type IsRepresentableFramesOptionParam struct {
PreferDF bool
ForceAsNDF bool
}

// IsRepresentableFramesOption represents IsRepresentableFrames option.
@@ -120,7 +124,7 @@ type IsRepresentableFramesOption func(*IsRepresentableFramesOptionParam)
// newIsRepresentableFramesOptionParam returns new IsRepresentableFramesOptionParam.
func newIsRepresentableFramesOptionParam() IsRepresentableFramesOptionParam {
return IsRepresentableFramesOptionParam{
PreferDF: true, // if frame rate is DF or NDF, assume DF
ForceAsNDF: true, // if frame rate is DF or NDF, assume NDF
}
}

@@ -136,7 +140,7 @@ func IsRepresentableFrames(frames uint64, num, den int32, opts ...IsRepresentabl
p := newIsRepresentableFramesOptionParam()
p.applyIsRepresentableFramesOption(opts...)

r, err := newRate(num, den, p.PreferDF)
r, err := newRate(num, den, p.ForceAsNDF)
if err != nil {
return false
}
@@ -145,9 +149,9 @@ func IsRepresentableFrames(frames uint64, num, den int32, opts ...IsRepresentabl

// TimecodeOptionParam represents timecode option parameter.
type TimecodeOptionParam struct {
PreferDF bool
Sep string
LastSep string
ForceAsNDF bool
Sep string
LastSep string
}

// TimecodeOption represents timecode option.
@@ -156,9 +160,9 @@ type TimecodeOption func(*TimecodeOptionParam)
// newTimecodeOptionParam returns new TimecodeOptionParam.
func newTimecodeOptionParam() TimecodeOptionParam {
return TimecodeOptionParam{
PreferDF: true, // if frame rate is 29.97 or 59.94, assume DF. otherwise, assume NDF
Sep: ":",
LastSep: ":",
ForceAsNDF: false, // true, if frame rate is DF or NDF, assume NDF. otherwise, assume DF
Sep: ":",
LastSep: ":",
}
}

@@ -174,7 +178,7 @@ func NewTimecode(frames uint64, num, den int32, opts ...TimecodeOption) (*Timeco
p := newTimecodeOptionParam()
p.applyTimecodeOption(opts...)

r, err := newRate(num, den, p.PreferDF)
r, err := newRate(num, den, p.ForceAsNDF)
if err != nil {
return nil, err
}
@@ -185,10 +189,10 @@ func NewTimecode(frames uint64, num, den int32, opts ...TimecodeOption) (*Timeco
}

tc, err := Reset(&Timecode{
preferDF: p.PreferDF,
sep: p.Sep,
lastSep: lastSep,
r: r,
forceAsNDF: p.ForceAsNDF,
sep: p.Sep,
lastSep: lastSep,
r: r,
}, frames)
if err != nil {
return nil, err
@@ -198,9 +202,9 @@ func NewTimecode(frames uint64, num, den int32, opts ...TimecodeOption) (*Timeco

// TimecodeOptionParam represents timecode option parameter.
type ParseTimecodeOptionParam struct {
PreferDF bool
Sep string
LastSep string
ForceAsNDF bool
Sep string
LastSep string
}

// ParseTimecodeOption represents parse timecode option.
@@ -209,7 +213,7 @@ type ParseTimecodeOption func(*ParseTimecodeOptionParam)
// newParseTimecodeOptionParam returns new ParseTimecodeOptionParam.
func newParseTimecodeOptionParam() ParseTimecodeOptionParam {
return ParseTimecodeOptionParam{
PreferDF: true, // if frame rate is 29.97 or 59.94, assume DF. otherwise, assume NDF
ForceAsNDF: false, // if frame rate is 29.97 or 59.94, assume NDF. otherwise, assume DF
}
}

@@ -225,7 +229,7 @@ func ParseTimecode(s string, num, den int32, opts ...ParseTimecodeOption) (*Time
p := newParseTimecodeOptionParam()
p.applyParseTimecodeOption(opts...)

r, err := newRate(num, den, p.PreferDF)
r, err := newRate(num, den, p.ForceAsNDF)
if err != nil {
return nil, err
}
@@ -252,14 +256,14 @@ func ParseTimecode(s string, num, den int32, opts ...ParseTimecodeOption) (*Time
}

return &Timecode{
preferDF: p.PreferDF,
sep: sep,
lastSep: lastSep,
r: r,
HH: uint64(hh),
MM: uint64(mm),
SS: uint64(ss),
FF: uint64(ff),
forceAsNDF: p.ForceAsNDF,
sep: sep,
lastSep: lastSep,
r: r,
HH: uint64(hh),
MM: uint64(mm),
SS: uint64(ss),
FF: uint64(ff),
}, nil
}

195 changes: 94 additions & 101 deletions timecode/timecode_test.go
Original file line number Diff line number Diff line change
@@ -9,263 +9,260 @@ import (

func TestNewRate(t *testing.T) {
t.Run("NaN", func(t *testing.T) {
_, err := newRate(1, 0, true)
_, err := newRate(1, 0, false)
assert.Error(t, err)
})
t.Run("0fps", func(t *testing.T) {
_, err := newRate(0, 1001, true)
_, err := newRate(0, 1001, false)
assert.Error(t, err)
})
t.Run("1fps", func(t *testing.T) {
_, err := newRate(1, 1, true)
_, err := newRate(1, 1, false)
assert.Error(t, err)
})
t.Run("23.976fps", func(t *testing.T) {
r, err := newRate(24000, 1001, true)
r, err := newRate(24000, 1001, false)
assert.NoError(t, err)
assert.Equal(t, 24, r.roundFPS)
assert.Equal(t, 0, r.dropFrames)
assert.Equal(t, 24*60, r.framesPer1Min)
assert.Equal(t, 24*600, r.framesPer10Min)
})
t.Run("24fps", func(t *testing.T) {
r, err := newRate(24, 1, true)
r, err := newRate(24, 1, false)
assert.NoError(t, err)
assert.Equal(t, 24, r.roundFPS)
assert.Equal(t, 0, r.dropFrames)
assert.Equal(t, 24*60, r.framesPer1Min)
assert.Equal(t, 24*600, r.framesPer10Min)
})
t.Run("25fps", func(t *testing.T) {
r, err := newRate(25, 1, true)
r, err := newRate(25, 1, false)
assert.NoError(t, err)
assert.Equal(t, 25, r.roundFPS)
assert.Equal(t, 0, r.dropFrames)
assert.Equal(t, 25*60, r.framesPer1Min)
assert.Equal(t, 25*600, r.framesPer10Min)
})
t.Run("29.97fps", func(t *testing.T) {
r, err := newRate(30000, 1001, true)
r, err := newRate(30000, 1001, false)
assert.NoError(t, err)
assert.Equal(t, 30, r.roundFPS)
assert.Equal(t, 2, r.dropFrames)
assert.Equal(t, 30*60-2, r.framesPer1Min)
assert.Equal(t, 30*600-9*2, r.framesPer10Min)
})
t.Run("30fps", func(t *testing.T) {
r, err := newRate(30, 1, true)
r, err := newRate(30, 1, false)
assert.NoError(t, err)
assert.Equal(t, 30, r.roundFPS)
assert.Equal(t, 0, r.dropFrames)
assert.Equal(t, 30*60, r.framesPer1Min)
assert.Equal(t, 30*600, r.framesPer10Min)
})
t.Run("48fps", func(t *testing.T) {
r, err := newRate(48, 1, true)
r, err := newRate(48, 1, false)
assert.NoError(t, err)
assert.Equal(t, 48, r.roundFPS)
assert.Equal(t, 0, r.dropFrames)
assert.Equal(t, 48*60, r.framesPer1Min)
assert.Equal(t, 48*600, r.framesPer10Min)
})
t.Run("50fps", func(t *testing.T) {
r, err := newRate(50, 1, true)
r, err := newRate(50, 1, false)
assert.NoError(t, err)
assert.Equal(t, 50, r.roundFPS)
assert.Equal(t, 0, r.dropFrames)
assert.Equal(t, 50*60, r.framesPer1Min)
assert.Equal(t, 50*600, r.framesPer10Min)
})
t.Run("59.94fps", func(t *testing.T) {
r, err := newRate(60000, 1001, true)
r, err := newRate(60000, 1001, false)
assert.NoError(t, err)
assert.Equal(t, 60, r.roundFPS)
assert.Equal(t, 4, r.dropFrames)
assert.Equal(t, 60*60-4, r.framesPer1Min)
assert.Equal(t, 60*600-9*4, r.framesPer10Min)
})
t.Run("60fps", func(t *testing.T) {
r, err := newRate(60, 1, true)
r, err := newRate(60, 1, false)
assert.NoError(t, err)
assert.Equal(t, 60, r.roundFPS)
assert.Equal(t, 0, r.dropFrames)
assert.Equal(t, 60*60, r.framesPer1Min)
assert.Equal(t, 60*600, r.framesPer10Min)
})
t.Run("error/23.995fps", func(t *testing.T) {
r, err := newRate(29995, 1000, true)
r, err := newRate(29995, 1000, false)
assert.Equal(t, ErrUnsupportedFrameRate, err)
assert.Nil(t, r)
})
t.Run("error/23.997fps", func(t *testing.T) {
r, err := newRate(29997, 1000, true)
r, err := newRate(29997, 1000, false)
assert.Equal(t, ErrUnsupportedFrameRate, err)
assert.Nil(t, r)
})
t.Run("error/29.96fps", func(t *testing.T) {
r, err := newRate(29960, 1000, true)
r, err := newRate(29960, 1000, false)
assert.Equal(t, ErrUnsupportedFrameRate, err)
assert.Nil(t, r)
})
t.Run("error/29.98fps", func(t *testing.T) {
r, err := newRate(29980, 1000, true)
r, err := newRate(29980, 1000, false)
assert.Equal(t, ErrUnsupportedFrameRate, err)
assert.Nil(t, r)
})
t.Run("error/59.93fps", func(t *testing.T) {
r, err := newRate(59930, 1000, true)
r, err := newRate(59930, 1000, false)
assert.Equal(t, ErrUnsupportedFrameRate, err)
assert.Nil(t, r)
})
t.Run("error/59.95fps", func(t *testing.T) {
r, err := newRate(59950, 1000, true)
r, err := newRate(59950, 1000, false)
assert.Equal(t, ErrUnsupportedFrameRate, err)
assert.Nil(t, r)
})
t.Run("error/60.001fps", func(t *testing.T) {
r, err := newRate(60001, 1000, true)
r, err := newRate(60001, 1000, false)
assert.Equal(t, ErrUnsupportedFrameRate, err)
assert.Nil(t, r)
})
}

func TestNewTimecodeNDF(t *testing.T) {
assumeDF := func(p *TimecodeOptionParam) {
p.PreferDF = true
}
assumeNDF := func(p *TimecodeOptionParam) {
p.PreferDF = false
p.ForceAsNDF = true
}

t.Run("NaN", func(t *testing.T) {
_, err := NewTimecode(1, 1, 0, assumeDF)
_, err := NewTimecode(1, 1, 0)
assert.Error(t, err)
})
t.Run("0fps", func(t *testing.T) {
_, err := NewTimecode(1, 0, 1001, assumeDF)
_, err := NewTimecode(1, 0, 1001)
assert.Error(t, err)
})
t.Run("1fps", func(t *testing.T) {
_, err := NewTimecode(1, 1, 1, assumeDF)
_, err := NewTimecode(1, 1, 1)
assert.Error(t, err)
})
t.Run("23.976fps", func(t *testing.T) {
tc, err := NewTimecode(1439, 24000, 1001, assumeDF)
tc, err := NewTimecode(1439, 24000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:23", tc.String())
assert.Equal(t, uint64(1439), tc.Frames())
assert.Equal(t, 60.018, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(1440, 24000, 1001, assumeDF)
tc, err = NewTimecode(1440, 24000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:00", tc.String())
assert.Equal(t, uint64(1440), tc.Frames())

tc, err = NewTimecode(1441, 24000, 1001, assumeDF)
tc, err = NewTimecode(1441, 24000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:01", tc.String())
assert.Equal(t, uint64(1441), tc.Frames())

tc, err = NewTimecode(1440*10, 24000, 1001, assumeDF)
tc, err = NewTimecode(1440*10, 24000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:00", tc.String())
assert.Equal(t, uint64(1440*10), tc.Frames())
assert.Equal(t, 600.601, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(1440*10+1, 24000, 1001, assumeDF)
tc, err = NewTimecode(1440*10+1, 24000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:01", tc.String())
assert.Equal(t, uint64(1440*10+1), tc.Frames())

maxFrames := uint64(24*6*(1440*10)) - 1
tc, err = NewTimecode(maxFrames, 24000, 1001, assumeDF)
tc, err = NewTimecode(maxFrames, 24000, 1001)
assert.NoError(t, err)
assert.Equal(t, "23:59:59:23", tc.String())
assert.Equal(t, maxFrames, tc.Frames())

tc, err = NewTimecode(maxFrames+1, 24000, 1001, assumeDF)
tc, err = NewTimecode(maxFrames+1, 24000, 1001)
assert.Equal(t, ErrTooManyFrames, err)
assert.Nil(t, tc)
})
t.Run("24fps", func(t *testing.T) {
tc, err := NewTimecode(1439, 24, 1, assumeDF)
tc, err := NewTimecode(1439, 24, 1)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:23", tc.String())
assert.Equal(t, uint64(1439), tc.Frames())
assert.Equal(t, 59.958, math.Round(tc.Duration().Seconds()*1000)/1000)
assert.Equal(t, int32(24), tc.FramerateNumerator())
assert.Equal(t, int32(1), tc.FramerateDenominator())

tc, err = NewTimecode(1440, 24, 1, assumeDF)
tc, err = NewTimecode(1440, 24, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:00", tc.String())
assert.Equal(t, uint64(1440), tc.Frames())

tc, err = NewTimecode(1441, 24, 1, assumeDF)
tc, err = NewTimecode(1441, 24, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:01", tc.String())
assert.Equal(t, uint64(1441), tc.Frames())

tc, err = NewTimecode(1440*10, 24, 1, assumeDF)
tc, err = NewTimecode(1440*10, 24, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:00", tc.String())
assert.Equal(t, uint64(1440*10), tc.Frames())
assert.Equal(t, 600.0, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(1440*10+1, 24, 1, assumeDF)
tc, err = NewTimecode(1440*10+1, 24, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:01", tc.String())
assert.Equal(t, uint64(1440*10+1), tc.Frames())

maxFrames := uint64(24*6*(1440*10)) - 1
tc, err = NewTimecode(maxFrames, 24, 1, assumeDF)
tc, err = NewTimecode(maxFrames, 24, 1)
assert.NoError(t, err)
assert.Equal(t, "23:59:59:23", tc.String())
assert.Equal(t, maxFrames, tc.Frames())
assert.Equal(t, 86399.958, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(maxFrames+1, 24, 1, assumeDF)
tc, err = NewTimecode(maxFrames+1, 24, 1)
assert.Equal(t, ErrTooManyFrames, err)
assert.Nil(t, tc)
})
t.Run("25", func(t *testing.T) {
tc, err := NewTimecode(1499, 25, 1, assumeDF)
tc, err := NewTimecode(1499, 25, 1)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:24", tc.String())
assert.Equal(t, uint64(1499), tc.Frames())
assert.Equal(t, 59.96, math.Round(tc.Duration().Seconds()*1000)/1000)
assert.Equal(t, int32(25), tc.FramerateNumerator())
assert.Equal(t, int32(1), tc.FramerateDenominator())

tc, err = NewTimecode(1500, 25, 1, assumeDF)
tc, err = NewTimecode(1500, 25, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:00", tc.String())
assert.Equal(t, uint64(1500), tc.Frames())

tc, err = NewTimecode(1501, 25, 1, assumeDF)
tc, err = NewTimecode(1501, 25, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:01", tc.String())
assert.Equal(t, uint64(1501), tc.Frames())

tc, err = NewTimecode(1500*10, 25, 1, assumeDF)
tc, err = NewTimecode(1500*10, 25, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:00", tc.String())
assert.Equal(t, uint64(1500*10), tc.Frames())
assert.Equal(t, 600.0, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(1500*10+1, 25, 1, assumeDF)
tc, err = NewTimecode(1500*10+1, 25, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:01", tc.String())
assert.Equal(t, uint64(1500*10+1), tc.Frames())

maxFrames := uint64(24*6*(1500*10)) - 1
tc, err = NewTimecode(maxFrames, 25, 1, assumeDF)
tc, err = NewTimecode(maxFrames, 25, 1)
assert.NoError(t, err)
assert.Equal(t, "23:59:59:24", tc.String())
assert.Equal(t, maxFrames, tc.Frames())
assert.Equal(t, 86399.96, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(maxFrames+1, 25, 1, assumeDF)
tc, err = NewTimecode(maxFrames+1, 25, 1)
assert.Equal(t, ErrTooManyFrames, err)
assert.Nil(t, tc)
})
@@ -311,125 +308,125 @@ func TestNewTimecodeNDF(t *testing.T) {
assert.Nil(t, tc)
})
t.Run("30fps", func(t *testing.T) {
tc, err := NewTimecode(1799, 30, 1, assumeDF)
tc, err := NewTimecode(1799, 30, 1)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:29", tc.String())
assert.Equal(t, uint64(1799), tc.Frames())
assert.Equal(t, 59.967, math.Round(tc.Duration().Seconds()*1000)/1000)
assert.Equal(t, int32(30), tc.FramerateNumerator())
assert.Equal(t, int32(1), tc.FramerateDenominator())

tc, err = NewTimecode(1800, 30, 1, assumeDF)
tc, err = NewTimecode(1800, 30, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:00", tc.String())
assert.Equal(t, uint64(1800), tc.Frames())

tc, err = NewTimecode(1801, 30, 1, assumeDF)
tc, err = NewTimecode(1801, 30, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:01", tc.String())
assert.Equal(t, uint64(1801), tc.Frames())

tc, err = NewTimecode(1800*10, 30, 1, assumeDF)
tc, err = NewTimecode(1800*10, 30, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:00", tc.String())
assert.Equal(t, uint64(1800*10), tc.Frames())
assert.Equal(t, 600.0, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(1800*10+1, 30, 1, assumeDF)
tc, err = NewTimecode(1800*10+1, 30, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:01", tc.String())
assert.Equal(t, uint64(1800*10+1), tc.Frames())

maxFrames := uint64(24*6*(1800*10)) - 1
tc, err = NewTimecode(maxFrames, 30, 1, assumeDF)
tc, err = NewTimecode(maxFrames, 30, 1)
assert.NoError(t, err)
assert.Equal(t, "23:59:59:29", tc.String())
assert.Equal(t, maxFrames, tc.Frames())
assert.Equal(t, 86399.967, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(maxFrames+1, 30, 1, assumeDF)
tc, err = NewTimecode(maxFrames+1, 30, 1)
assert.Equal(t, ErrTooManyFrames, err)
assert.Nil(t, tc)
})
t.Run("48", func(t *testing.T) {
tc, err := NewTimecode(2879, 48, 1, assumeDF)
tc, err := NewTimecode(2879, 48, 1)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:47", tc.String())
assert.Equal(t, uint64(2879), tc.Frames())
assert.Equal(t, 59.979, math.Round(tc.Duration().Seconds()*1000)/1000)
assert.Equal(t, int32(48), tc.FramerateNumerator())
assert.Equal(t, int32(1), tc.FramerateDenominator())

tc, err = NewTimecode(2880, 48, 1, assumeDF)
tc, err = NewTimecode(2880, 48, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:00", tc.String())
assert.Equal(t, uint64(2880), tc.Frames())

tc, err = NewTimecode(2881, 48, 1, assumeDF)
tc, err = NewTimecode(2881, 48, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:01", tc.String())
assert.Equal(t, uint64(2881), tc.Frames())

tc, err = NewTimecode(2880*10, 48, 1, assumeDF)
tc, err = NewTimecode(2880*10, 48, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:00", tc.String())
assert.Equal(t, uint64(2880*10), tc.Frames())
assert.Equal(t, 600.0, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(2880*10+1, 48, 1, assumeDF)
tc, err = NewTimecode(2880*10+1, 48, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:01", tc.String())
assert.Equal(t, uint64(2880*10+1), tc.Frames())

maxFrames := uint64(24*6*(2880*10)) - 1
tc, err = NewTimecode(maxFrames, 48, 1, assumeDF)
tc, err = NewTimecode(maxFrames, 48, 1)
assert.NoError(t, err)
assert.Equal(t, "23:59:59:47", tc.String())
assert.Equal(t, maxFrames, tc.Frames())
assert.Equal(t, 86399.979, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(maxFrames+1, 48, 1, assumeDF)
tc, err = NewTimecode(maxFrames+1, 48, 1)
assert.Equal(t, ErrTooManyFrames, err)
assert.Nil(t, tc)
})
t.Run("50fps", func(t *testing.T) {
tc, err := NewTimecode(2999, 50, 1, assumeDF)
tc, err := NewTimecode(2999, 50, 1)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:49", tc.String())
assert.Equal(t, uint64(2999), tc.Frames())
assert.Equal(t, 59.98, math.Round(tc.Duration().Seconds()*1000)/1000)
assert.Equal(t, int32(50), tc.FramerateNumerator())
assert.Equal(t, int32(1), tc.FramerateDenominator())

tc, err = NewTimecode(3000, 50, 1, assumeDF)
tc, err = NewTimecode(3000, 50, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:00", tc.String())
assert.Equal(t, uint64(3000), tc.Frames())

tc, err = NewTimecode(3001, 50, 1, assumeDF)
tc, err = NewTimecode(3001, 50, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:01", tc.String())
assert.Equal(t, uint64(3001), tc.Frames())

tc, err = NewTimecode(3000*10, 50, 1, assumeDF)
tc, err = NewTimecode(3000*10, 50, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:00", tc.String())
assert.Equal(t, uint64(3000*10), tc.Frames())
assert.Equal(t, 600.0, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(3000*10+1, 50, 1, assumeDF)
tc, err = NewTimecode(3000*10+1, 50, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:01", tc.String())
assert.Equal(t, uint64(3000*10+1), tc.Frames())

maxFrames := uint64(24*6*(3000*10)) - 1
tc, err = NewTimecode(maxFrames, 50, 1, assumeDF)
tc, err = NewTimecode(maxFrames, 50, 1)
assert.NoError(t, err)
assert.Equal(t, "23:59:59:49", tc.String())
assert.Equal(t, maxFrames, tc.Frames())
assert.Equal(t, 86399.98, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(maxFrames+1, 50, 1, assumeDF)
tc, err = NewTimecode(maxFrames+1, 50, 1)
assert.Equal(t, ErrTooManyFrames, err)
assert.Nil(t, tc)
})
@@ -480,147 +477,143 @@ func TestNewTimecodeNDF(t *testing.T) {
assert.Nil(t, tc)
})
t.Run("60fps", func(t *testing.T) {
tc, err := NewTimecode(0, 60, 1, assumeDF)
tc, err := NewTimecode(0, 60, 1)
assert.NoError(t, err)
assert.Equal(t, "00:00:00:00", tc.String())
assert.Equal(t, uint64(0), tc.Frames())
assert.Equal(t, 0.0, math.Round(tc.Duration().Seconds()*1000)/1000)
assert.Equal(t, int32(60), tc.FramerateNumerator())
assert.Equal(t, int32(1), tc.FramerateDenominator())

tc, err = NewTimecode(3599, 60, 1, assumeDF)
tc, err = NewTimecode(3599, 60, 1)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:59", tc.String())
assert.Equal(t, uint64(3599), tc.Frames())

tc, err = NewTimecode(3600, 60, 1, assumeDF)
tc, err = NewTimecode(3600, 60, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:00", tc.String())
assert.Equal(t, uint64(3600), tc.Frames())

tc, err = NewTimecode(3601, 60, 1, assumeDF)
tc, err = NewTimecode(3601, 60, 1)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:01", tc.String())
assert.Equal(t, uint64(3601), tc.Frames())

tc, err = NewTimecode(3600*10, 60, 1, assumeDF)
tc, err = NewTimecode(3600*10, 60, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:00", tc.String())
assert.Equal(t, uint64(3600*10), tc.Frames())
assert.Equal(t, 600.0, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(3600*10+1, 60, 1, assumeDF)
tc, err = NewTimecode(3600*10+1, 60, 1)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:01", tc.String())
assert.Equal(t, uint64(3600*10+1), tc.Frames())

maxFrames := uint64(24*6*(3600*10)) - 1
tc, err = NewTimecode(maxFrames, 60, 1, assumeDF)
tc, err = NewTimecode(maxFrames, 60, 1)
assert.NoError(t, err)
assert.Equal(t, "23:59:59:59", tc.String())
assert.Equal(t, maxFrames, tc.Frames())
assert.Equal(t, 86399.983, math.Round(tc.Duration().Seconds()*1000)/1000)

tc, err = NewTimecode(maxFrames+1, 60, 1, assumeDF)
tc, err = NewTimecode(maxFrames+1, 60, 1)
assert.Equal(t, ErrTooManyFrames, err)
assert.Nil(t, tc)
})
}

func TestNewTimecodeDF(t *testing.T) {
assumeDF := func(p *TimecodeOptionParam) {
p.PreferDF = true
}

t.Run("30DF", func(t *testing.T) {
tc, err := NewTimecode(1798, 30000, 1001, assumeDF)
tc, err := NewTimecode(1798, 30000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:28", tc.String())
assert.Equal(t, uint64(1798), tc.Frames())

tc, err = NewTimecode(1799, 30000, 1001, assumeDF)
tc, err = NewTimecode(1799, 30000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:29", tc.String())
assert.Equal(t, uint64(1799), tc.Frames())

tc, err = NewTimecode(1800, 30000, 1001, assumeDF)
tc, err = NewTimecode(1800, 30000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:02", tc.String())
assert.Equal(t, uint64(1800), tc.Frames())

tc, err = NewTimecode(1800+1798*8, 30000, 1001, assumeDF)
tc, err = NewTimecode(1800+1798*8, 30000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:09:00:02", tc.String())
assert.Equal(t, uint64(1800+1798*8), tc.Frames())

tc, err = NewTimecode(1800+1798*9, 30000, 1001, assumeDF)
tc, err = NewTimecode(1800+1798*9, 30000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:00", tc.String())
assert.Equal(t, uint64(1800+1798*9), tc.Frames())

tc, err = NewTimecode(1800+1798*9+1799, 30000, 1001, assumeDF)
tc, err = NewTimecode(1800+1798*9+1799, 30000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:10:59:29", tc.String())
assert.Equal(t, uint64(1800+1798*9+1799), tc.Frames())

tc, err = NewTimecode(1800+1798*9+1800, 30000, 1001, assumeDF)
tc, err = NewTimecode(1800+1798*9+1800, 30000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:11:00:02", tc.String())
assert.Equal(t, uint64(1800+1798*9+1800), tc.Frames())

maxFrames := uint64(24*6*(1800+1798*9)) - 1
tc, err = NewTimecode(maxFrames, 30000, 1001, assumeDF)
tc, err = NewTimecode(maxFrames, 30000, 1001)
assert.NoError(t, err)
assert.Equal(t, "23:59:59:29", tc.String())
assert.Equal(t, maxFrames, tc.Frames())

tc, err = NewTimecode(maxFrames+1, 30000, 1001, assumeDF)
tc, err = NewTimecode(maxFrames+1, 30000, 1001)
assert.Equal(t, ErrTooManyFrames, err)
assert.Nil(t, tc)
})
t.Run("60DF", func(t *testing.T) {
tc, err := NewTimecode(3596, 60000, 1001, assumeDF)
tc, err := NewTimecode(3596, 60000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:56", tc.String())
assert.Equal(t, uint64(3596), tc.Frames())

tc, err = NewTimecode(3599, 60000, 1001, assumeDF)
tc, err = NewTimecode(3599, 60000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:00:59:59", tc.String())
assert.Equal(t, uint64(3599), tc.Frames())

tc, err = NewTimecode(3600, 60000, 1001, assumeDF)
tc, err = NewTimecode(3600, 60000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:01:00:04", tc.String())
assert.Equal(t, uint64(3600), tc.Frames())

tc, err = NewTimecode(3600+3596*8, 60000, 1001, assumeDF)
tc, err = NewTimecode(3600+3596*8, 60000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:09:00:04", tc.String())
assert.Equal(t, uint64(3600+3596*8), tc.Frames())

tc, err = NewTimecode(3600+3596*9, 60000, 1001, assumeDF)
tc, err = NewTimecode(3600+3596*9, 60000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:10:00:00", tc.String())
assert.Equal(t, uint64(3600+3596*9), tc.Frames())

tc, err = NewTimecode(3600+3596*9+3599, 60000, 1001, assumeDF)
tc, err = NewTimecode(3600+3596*9+3599, 60000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:10:59:59", tc.String())
assert.Equal(t, uint64(3600+3596*9+3599), tc.Frames())

tc, err = NewTimecode(3600+3596*9+3600, 60000, 1001, assumeDF)
tc, err = NewTimecode(3600+3596*9+3600, 60000, 1001)
assert.NoError(t, err)
assert.Equal(t, "00:11:00:04", tc.String())
assert.Equal(t, uint64(3600+3596*9+3600), tc.Frames())

maxFrames := uint64(24*6*(3600+3596*9)) - 1
tc, err = NewTimecode(maxFrames, 60000, 1001, assumeDF)
tc, err = NewTimecode(maxFrames, 60000, 1001)
assert.NoError(t, err)
assert.Equal(t, "23:59:59:59", tc.String())
assert.Equal(t, maxFrames, tc.Frames())

tc, err = NewTimecode(maxFrames+1, 60000, 1001, assumeDF)
tc, err = NewTimecode(maxFrames+1, 60000, 1001)
assert.Equal(t, ErrTooManyFrames, err)
assert.Nil(t, tc)
})
@@ -637,7 +630,7 @@ func TestParseTimecode(t *testing.T) {
})
t.Run("ParseTimecode/29.97NDF", func(t *testing.T) {
tc, err := ParseTimecode("00:01:00;00", 30000, 1001, func(p *ParseTimecodeOptionParam) {
p.PreferDF = false
p.ForceAsNDF = true
}) // NDF
assert.NoError(t, err)
assert.Equal(t, "00:01:00:00", tc.String())
@@ -742,7 +735,7 @@ func TestAdd(t *testing.T) {
t.Run("Add/mismatch frame rate2", func(t *testing.T) {
tc1, _ := NewTimecode(1, 30000, 1001)
tc2, _ := NewTimecode(1, 30000, 1001, func(p *TimecodeOptionParam) {
p.PreferDF = false
p.ForceAsNDF = true
})
tc3, err := tc1.Add(tc2)
assert.Nil(t, tc3)
@@ -824,7 +817,7 @@ func TestTimecodeOption(t *testing.T) {
}
opt2 := func(p *TimecodeOptionParam) {
p.LastSep = ";"
p.PreferDF = false
p.ForceAsNDF = true
}
tc, err := NewTimecode(3596, 60000, 1001, opt1, opt2)
assert.NoError(t, err)

0 comments on commit 664f824

Please sign in to comment.